home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1996 #15 / Monster Media Number 15 (Monster Media)(July 1996).ISO / prog_gen / rawed1_1.zip / RAWEDIT.C < prev    next >
C/C++ Source or Header  |  1996-06-08  |  83KB  |  2,945 lines

  1. /* -- rawedit.c  View/edit a file in hex/ascii             -- */
  2.  
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <stdlib.h>
  6. #include <ctype.h>
  7. #include <math.h>
  8. #include <errno.h>
  9.  
  10. #include "rawedit.h"
  11.  
  12. /* --------------------- **
  13. **     M A C R O S       **
  14. ** --------------------- */
  15.  
  16. #define HEX_SIDE       0
  17. #define ASCII_SIDE     1
  18. #define STARTROW       3  
  19. #define MAXROW        24
  20. #define BYTES_PER_ROW 24
  21. #define BYTES_PER_PAGE ((MAXROW - STARTROW + 1) * BYTES_PER_ROW)
  22. #define HEX_COL_START     1
  23. #define ASCII_COL_START  56
  24. #define ASCII_LEN (BYTES_PER_ROW)
  25. #define HEX_LEN   ( (BYTES_PER_ROW * 2) + 6 )
  26.  
  27. #ifndef FALSE
  28.  #define FALSE 0
  29. #endif
  30.  
  31. #ifndef TRUE
  32.  #define TRUE -1
  33. #endif
  34.  
  35. /* -------------------------------- **
  36. **  G L O B A L   V A R I A B L E S **
  37. ** -------------------------------- */
  38.  
  39. FILE *file;
  40. char *filename = (char *)0;
  41. short curx = 1, cury = 1;
  42. long  filelen = 0L, filepos = 0L;
  43. char  orig_buffer[ BYTES_PER_PAGE + 3 ];
  44. long  orig_filepos = -1L;
  45. char  buffer[ BYTES_PER_PAGE + 3 ];
  46. short bufpos=0, buflen=0;
  47. short nibblestate = 0;
  48. short tabstate = HEX_SIDE;
  49. char  search_direction = 'F';   /* F = forward, B = backward */
  50. char  search_type      = 'A';   /* H = hex, A = ascii */
  51. char  search_string[200];
  52. short search_string_len = 0;
  53. long  last_srch_pos  = 0;
  54. short read_only = 0;
  55.  
  56. char *cursor_help[] = {
  57.                  "   _____________________________________________   ",
  58.                  "  |                                             |  ", 
  59.                  "  |   RAWEDIT v1.1    By: Ken Martin            |  ",
  60.                  "  |        C U R S O R   K E Y S                |  ",
  61.                  "  |                                             |  ",
  62.                  "  | Up ............... UP-ARROW, CTRL-U         |  ",
  63.                  "  | Down ............. DOWN-ARROW, CTRL-D       |  ",
  64.                  "  | Previous Page .... PAGE-UP, CTRL-P          |  ",
  65.                  "  | Next Page ........ PAGE-DOWN, CTRL-N        |  ",
  66.                  "  | Left ............. LEFT-ARROW, CTRL-L       |  ",
  67.                  "  | Right ............ RIGHT-ARROW, CTRL-R      |  ",
  68.                  "  | Beginning of file. HOME, CTRL-H             |  ",
  69.                  "  | End of file ...... END, CTRL-E              |  ",
  70.                  "  | Jump ............. TAB, CTRL-I              |  ",
  71.                  "  | Menu ............. ENTER, CTRL-M            |  ",
  72.                  "  | Exit ............. ESCAPE, CTRL-C           |  ",
  73.                  "  | Help (in menu) ... ?                        |  ",
  74.                  "  |                                             |  ",
  75.                  "  | Hit any key to continue...                  |  ",
  76.                  "  |_____________________________________________|  ",
  77.                  "                                                   ",
  78.                  "                                                   ",
  79.                  "\0"
  80.                };
  81.  
  82. char *main_menu_help[] = {
  83.                  "   _____________________________________________   ",
  84.                  "  |                                             |  ", 
  85.                  "  |   RAWEDIT HELP:  Main Menu                  |  ",
  86.                  "  |                                             |  ",
  87.                  "  | Exit ............ Leave the RAWEDIT program |  ",
  88.                  "  | Goto ............ Goto an offset# in file   |  ",
  89.                  "  | Search ...... ... Search for a string       |  ",
  90.                  "  | Repeat_search ... Repeat search using       |  ",
  91.                  "  |                   previous search parameters|  ",
  92.                  "  | re-Draw_screen .. Redisplay entire screen   |  ",
  93.                  "  | Help ............ Show cursor keys          |  ",
  94.                  "  | ? ............... Show this help screen.    |  ",
  95.                  "  |                                             |  ",
  96.                  "  | Access any menu option by pressing the      |  ",
  97.                  "  | corresponding capitalized letter.  For      |  ",
  98.                  "  | example, to exit RAWEDIT, press 'E'.        |  ",
  99.                  "  |                                             |  ",
  100.                  "  | Hit a key to continue...                    |  ",
  101.                  "  |                                             |  ",
  102.                  "  |_____________________________________________|  ",
  103.                  "                                                   ",
  104.                  "\0"
  105.                };
  106.  
  107. char *offset_num_help[] = {
  108.                  "   _____________________________________________   ",
  109.                  "  |                                             |  ", 
  110.                  "  |   RAWEDIT HELP:  Offset Number              |  ",
  111.                  "  |                                             |  ",
  112.                  "  | The offset # should be from 0 to file       |  ",
  113.                  "  | length (shown at the top of the screen).    |  ",
  114.                  "  |                                             |  ",
  115.                  "  | Offset # may be an integer (base 10), or    |  ",
  116.                  "  | hexadecimal.  For hexadecimal, prefix with  |  ",
  117.                  "  | '0x'.                                       |  ",
  118.                  "  |                                             |  ",
  119.                  "  | Examples:                                   |  ",
  120.                  "  |    Enter offset# to go: 1234                |  ",
  121.                  "  |    Enter offset# to go: 0xF1C4              |  ",
  122.                  "  |                                             |  ",
  123.                  "  | Hit a key to continue...                    |  ",
  124.                  "  |                                             |  ",
  125.                  "  |_____________________________________________|  ",
  126.                  "                                                   ",
  127.                  "\0"
  128.                };
  129.  
  130. char *search_direction_help[] = {
  131.                  "   _____________________________________________   ",
  132.                  "  |                                             |  ", 
  133.                  "  |   RAWEDIT HELP:  Search Direction           |  ",
  134.                  "  |                                             |  ",
  135.                  "  | To                                  Type    |  ",
  136.                  "  | ----------------------------------- ------- |  ",
  137.                  "  | Search forward from current offset  F       |  ",
  138.                  "  | Search backward from current offset B       |  ",
  139.                  "  | Return to previous menu             [ENTER] |  ",
  140.                  "  | Show this help screen               ?       |  ",
  141.                  "  |                                             |  ",
  142.                  "  |                                             |  ",
  143.                  "  | Hit a key to continue...                    |  ",
  144.                  "  |                                             |  ",
  145.                  "  |_____________________________________________|  ",
  146.                  "                                                   ",
  147.                  "\0"
  148.                };
  149.  
  150. char *search_type_help[] = {
  151.                  "   _____________________________________________   ",
  152.                  "  |                                             |  ", 
  153.                  "  |   RAWEDIT HELP:  Search Type                |  ",
  154.                  "  |                                             |  ",
  155.                  "  | To                                  Type    |  ",
  156.                  "  | ----------------------------------- ------- |  ",
  157.                  "  | Search using hexadecimal numbers    H       |  ",
  158.                  "  | Search using normal ASCII text      A       |  ",
  159.                  "  | Return to previous menu             [ENTER] |  ",
  160.                  "  | Show this help screen               ?       |  ",
  161.                  "  |                                             |  ",
  162.                  "  |                                             |  ",
  163.                  "  | Hit a key to continue...                    |  ",
  164.                  "  |                                             |  ",
  165.                  "  |_____________________________________________|  ",
  166.                  "                                                   ",
  167.                  "\0"
  168.                };
  169.  
  170. char *search_string_help[] = {
  171.                  "   _____________________________________________   ",
  172.                  "  |                                             |  ", 
  173.                  "  |   RAWEDIT HELP:  Search String              |  ",
  174.                  "  |                                             |  ",
  175.                  "  | Enter the ASCII text string to be used for  |  ",
  176.                  "  | searching.  RAWEDIT will then go to the     |  ",
  177.                  "  | first matching position in the file.        |  ",
  178.                  "  | A failure a match will return to the        |  ",
  179.                  "  | current offset position.                    |  ",
  180.                  "  |                                             |  ",
  181.                  "  | Hit a key to continue...                    |  ",
  182.                  "  |_____________________________________________|  ",
  183.                  "                                                   ",
  184.                  "\0"
  185.                };
  186.  
  187. char *search_hex_nums_help[] = {
  188.                  "   _____________________________________________   ",
  189.                  "  |                                             |  ", 
  190.                  "  |   RAWEDIT HELP:  Search Hex Nums            |  ",
  191.                  "  |                                             |  ",
  192.                  "  | Enter the hexadecimal numbers to be used for|  ",
  193.                  "  | searching.  RAWEDIT will then go to the     |  ",
  194.                  "  | first matching position in the file.        |  ",
  195.                  "  | A failure a match will return to the        |  ",
  196.                  "  | current offset position.                    |  ",
  197.                  "  |                                             |  ",
  198.                  "  | Examples:                                   |  ",
  199.                  "  |   search hex nums: A1C4010004               |  ",
  200.                  "  |   search hex nums: 00 01 39 CF              |  ",
  201.                  "  |   search hex nums: 0xF00F 0xC1 0x001A03     |  ",
  202.                  "  |                                             |  ",
  203.                  "  | Hit a key to continue...                    |  ",
  204.                  "  |_____________________________________________|  ",
  205.                  "                                                   ",
  206.                  "\0"
  207.                };
  208.  
  209. char *write_changes_help[] = {
  210.                  "   _____________________________________________   ",
  211.                  "  |                                             |  ", 
  212.                  "  |   RAWEDIT HELP:  Write changes              |  ",
  213.                  "  |                                             |  ",
  214.                  "  | Yes ...... Save changes made to this screen |  ",
  215.                  "  |                                             |  ",
  216.                  "  | No ....... Discard changes, this page will  |  ",
  217.                  "  |            not be altered.                  |  ",
  218.                  "  |                                             |  ",
  219.                  "  |                                             |  ",
  220.                  "  | Hit a key to continue...                    |  ",
  221.                  "  |_____________________________________________|  ",
  222.                  "                                                   ",
  223.                  "\0"
  224.                };
  225.  
  226. char *util_help[] = {
  227.                  "   _____________________________________________   ",
  228.                  "  |                                             |  ",
  229.                  "  |   RAWEDIT HELP:  Utilities                  |  ",
  230.                  "  |                                             |  ",
  231.                  "  | Expand_file.... Increase size of current    |  ",
  232.                  "  |                 file                        |  ",
  233.                  "  | Save_chunk..... Save a portion of this file |  ",
  234.                  "  |                 to a new file               |  ",
  235.                  "  | Hex_conv....... Convert hex to dec, hex to  |  ",
  236.                  "  |                 bin, dec to bin, dec to     |  ",
  237.                  "  |                 hex, bin to hex, bin to dec |  ",
  238.                  "  | Calc........... Simple scientific calculator|  ",
  239.                  "  |                                             |  ",
  240.                  "  | Hit a key to continue...                    |  ",
  241.                  "  |_____________________________________________|  ",
  242.                  "                                                   ",
  243.                  "\0"
  244.                };
  245. /* -------------------------------- **
  246. **     P R O T O T Y P E S          **
  247. ** ---------------------------------*/
  248.  
  249. int   rawedit( char *fname );
  250. void  display_header( void );
  251. void  refresh_screen( short firstrow, short lastrow );
  252. void  flush_buffer( void );
  253. int   get_buffer( void );
  254. void  compute_xy( short *x, short *y ); 
  255. char *get_hex( char ch );
  256. void  print_filename( void );
  257. void  update_position_display( void );
  258. void  do_page_up( long newbufpos );
  259. void  do_page_down( long newbufpos );
  260. void  do_right( void );
  261. int   do_menu( void );
  262. void  do_goto_offset( void );
  263. void  do_help( char *help_text[] );
  264. void  strip( char *s );
  265. int   hex_to_long( char *s, unsigned long *ret_val );
  266. char  hex_to_nibble( char c );
  267. void  message( char *msg );
  268. void  do_search( void );
  269. void  do_search_direction( void );
  270. void  do_search_type( void );
  271. void  do_repeat_search( void );
  272. void  do_utilities( void );
  273. void  do_setfilesize( void );
  274. void  do_savechunk( void );
  275. void  do_hexconv( void );
  276. void  calc(short col, short row);
  277. int   calc_error( char * action );
  278. void  search_file( long start_pos );
  279. int   copy_files( FILE *source, FILE *dest, long offset1, long offset2,
  280.                   char append);
  281. void  get_file_length( void );
  282. char *long_to_hex( long l );
  283. char *hex_to_bytes( char *hex, long *b_len);
  284. short input_line( char *editstr, short col, short row, short len,
  285.                   short startpos, int *exitlist, char *options );
  286. void  lstrip( char * );
  287. void  rstrip( char * );
  288. char  valid_char( char a );
  289. int   files_are_same( char *file1, char *file2 );
  290. char *long_to_bin( long l );
  291.  
  292.  
  293. /* -------------------- **
  294. **      M A I N         **
  295. ** ---------------------*/
  296.  
  297. int main(int argc, char *argv[])
  298. {
  299.   long i;
  300.     
  301.  
  302.   if ( argc < 2 )
  303.   {
  304.      printf(
  305.    "\n RAWEDIT  -  View a file in hex/ascii         "
  306.    "\n"
  307.    "\n       Syntax: rawedit -r <filename1> {<filename2> ...}"  
  308.    "\n"
  309.    "\n       where: -r          Read-only mode.  No file changes allowed."
  310.    "\n              <filename>  The file to view/modify."
  311.    "\n"
  312.               );
  313.      exit(1);
  314.   }
  315.  
  316.   io_init(); 
  317.   display_header();
  318.  
  319.   /* --- Check for switch --- */
  320.   for (i = 1; i < argc; i++ )
  321.   {
  322.     if ( strcmp( argv[i], "-r" ) == 0 )
  323.     {
  324.        read_only = 1;
  325.     }
  326.   }
  327.  
  328.   for (i = 1; i < argc; i++ )
  329.   {
  330.     if ( strcmp( argv[i], "-r" ) == 0 ) continue;
  331.     io_gotoxy(1,2);
  332.     io_printf("%80s", " ");
  333.     if ( !rawedit ( argv[i] ) )
  334.     {
  335.       io_refresh();
  336.       io_end();
  337.       exit(1);
  338.     }
  339.   }
  340.  
  341.   io_end();
  342.  
  343.   return 0;
  344. }
  345.  
  346.  
  347. /* ----------------------------------- **
  348. **  R A W E D I T   F U N C T I O N S  **
  349. ** ----------------------------------- */
  350.  
  351. void display_header( void )
  352. {
  353.    io_clrscr();
  354.    io_gotoxy( 26, 1 ); io_puts( "Len:" ); 
  355.    io_gotoxy( 41, 1 ); io_puts( "File Offset:" ); 
  356.    io_gotoxy( 1,  2 ); io_puts( "[ENTER]=Menu" ); 
  357.    io_refresh();
  358. }
  359.  
  360. int rawedit( char *fname )
  361. {
  362.   char tmp[100];
  363.   short keyhit;
  364.   short tmpx, tmpy;
  365.  
  366.   filename = fname;
  367.  
  368.   print_filename();
  369.  
  370.   /* ------------------------------- **
  371.   **   Open filename                 **
  372.   ** ------------------------------- */
  373.  
  374.   if ( read_only )
  375.   {
  376.     file = fopen( filename, "rb" );
  377.   }
  378.   else
  379.   {
  380.     file = fopen( filename, "r+b" );
  381.   }
  382.  
  383.   if ( file == (FILE *)0 )
  384.   {
  385.     io_clrscr();
  386.     sprintf( tmp, "Unable to open %s.  Hit a key...", filename );
  387.     message( tmp );
  388.     return 1;
  389.   }
  390.  
  391.  
  392.   /* ------------------------------- **
  393.   **   Display initial file info     **
  394.   ** ------------------------------- */
  395.   get_file_length();
  396.  
  397.   fseek( file, 0L, SEEK_SET );  /* Reset to beginning */
  398.  
  399.   if ( get_buffer() ) return 1;
  400.   io_gotoxy( 1, 2 );
  401.   io_printf("[ENTER]=Menu %65.65s", " " );
  402.   refresh_screen( STARTROW, MAXROW );
  403.  
  404.  
  405.   /* ------------------------------- **
  406.   **   Get keystroke and process     **
  407.   ** --------------------------------*/
  408.   while( 1 )
  409.   {
  410.      update_position_display();
  411.  
  412.      compute_xy( &curx, &cury );
  413.      io_gotoxy( curx, cury );
  414.  
  415.      io_refresh(); 
  416.      keyhit = io_inchar();
  417.  
  418.      if ( keyhit == io_ESCAPE || keyhit ==  io_CTRL_C ) 
  419.      {
  420.           break;
  421.      }
  422.      else if ( keyhit == io_TAB || keyhit == io_CTRL_I )  /* Jump  */
  423.      {
  424.           tabstate = 1 - tabstate;
  425.           nibblestate = 0;
  426.      }
  427.      else if ( keyhit == io_PAGEUP || keyhit == io_CTRL_P )
  428.      {
  429.           do_page_up( bufpos );
  430.      }
  431.      else if ( keyhit == io_PAGEDOWN || keyhit == io_CTRL_N )
  432.      {
  433.           do_page_down( bufpos );
  434.      }
  435.      else if ( keyhit == io_UP || keyhit == io_CTRL_U )
  436.      {
  437.           if ( bufpos - BYTES_PER_ROW  >= 0 )
  438.           {
  439.              bufpos -= BYTES_PER_ROW;
  440.           }
  441.           else
  442.           {
  443.             if ( filepos > 0L )
  444.             {
  445.               if ( filepos < BYTES_PER_PAGE )
  446.               {
  447.                 do_page_up( filepos - BYTES_PER_ROW );
  448.               }
  449.               else
  450.               {
  451.                 do_page_up( BYTES_PER_PAGE - BYTES_PER_ROW + bufpos );
  452.               }
  453.             }
  454.           }
  455.      }
  456.      else if ( keyhit == io_DOWN || keyhit == io_CTRL_D )
  457.      {
  458.           if ( bufpos + BYTES_PER_ROW  < buflen )
  459.           {
  460.              bufpos += BYTES_PER_ROW;
  461.           }
  462.           else
  463.           {
  464.             do_page_down( bufpos - BYTES_PER_PAGE + BYTES_PER_ROW );
  465.           }
  466.      }
  467.      else if ( keyhit == io_LEFT || keyhit == io_CTRL_L )
  468.      {
  469.           if ( tabstate == ASCII_SIDE ) /* --- Ascii area --- */
  470.           {
  471.             if ( bufpos > 0 )
  472.                 bufpos--;
  473.             else
  474.             {
  475.               if ( filepos < BYTES_PER_PAGE )
  476.               {
  477.                 do_page_up( filepos - 1L );
  478.               }
  479.               else
  480.               {
  481.                 do_page_up( BYTES_PER_PAGE );
  482.               }
  483.             }
  484.           }
  485.           else /* --- Hex text area --- */
  486.           {
  487.             if ( nibblestate )
  488.             {
  489.               nibblestate = 0;
  490.             }
  491.             else
  492.             {
  493.               if ( bufpos > 0 )
  494.               {
  495.                  bufpos--;
  496.                  nibblestate = 1;
  497.               }
  498.               else
  499.               {
  500.                 if ( filepos > 0L )
  501.                 {
  502.                   if ( filepos < BYTES_PER_PAGE )
  503.                   {
  504.                     do_page_up( filepos - 1L );
  505.                   }
  506.                   else
  507.                   {
  508.  
  509.                     do_page_up( BYTES_PER_PAGE );
  510.                   }
  511.                 }
  512.               }
  513.             }
  514.           }
  515.      }
  516.      else if ( keyhit == io_RIGHT || keyhit == io_CTRL_R )
  517.      {
  518.        do_right();
  519.      }
  520.      /* --- Beginning of file --- */
  521.      else if ( keyhit == io_HOME || keyhit == io_CTRL_H )
  522.      {
  523.        filepos = 0L;
  524.        bufpos = 0;
  525.  
  526.        if ( get_buffer() ) return 1;
  527.        refresh_screen( STARTROW, MAXROW );
  528.  
  529.      }
  530.  
  531.      /* --- End of file --- */
  532.      else if ( keyhit == io_END || keyhit == io_CTRL_E )
  533.      {
  534.        get_file_length( );
  535.        
  536.        filepos = filelen - BYTES_PER_PAGE + BYTES_PER_ROW;
  537.  
  538.        if ( filepos >= filelen ) filepos = filelen - 1L;
  539.        if ( filepos < 0L ) filepos = 0L;
  540.  
  541.        bufpos = filelen - filepos - 1L;
  542.  
  543.        if ( get_buffer() ) return 1;
  544.        refresh_screen( STARTROW, MAXROW );
  545.      }
  546.  
  547.      /* ----- Activate Menu ----- */
  548.      else if ( keyhit == io_ENTER || keyhit == io_CTRL_M )
  549.      {
  550.         if ( do_menu() ) break;
  551.         io_gotoxy( 1, 2 );
  552.         io_printf("[ENTER]=Menu %65.65s", " " );
  553.      }
  554.      /* --- Modify the buffer --- */
  555.      else if ( !read_only && keyhit >=(short)32 && keyhit <= (short)io_MAX_VALID_CHARACTER )
  556.      {
  557.        if ( tabstate == HEX_SIDE )
  558.        { /*  --- Hex side, allow only hex characters --- */
  559.          keyhit = (short)toupper( (int)keyhit );
  560.          if ( (keyhit >= (short)'0' && keyhit <= (short)'9') ||
  561.               (keyhit >= (short)'A' && keyhit <= (short)'F')
  562.             )
  563.          {
  564.             if ( nibblestate == 0 )  /* --- Upper nibble --- */
  565.             {
  566.                 buffer[bufpos] =
  567.                   ( buffer[bufpos] & 0x0F ) |
  568.                   ( hex_to_nibble( (char)keyhit ) << 4 );
  569.             }
  570.             else  /* --- Lower nibble --- */
  571.             {
  572.                 buffer[bufpos] =
  573.                   ( buffer[bufpos] & 0xF0 ) |
  574.                   hex_to_nibble( (char)keyhit );
  575.             }
  576.  
  577.             /* --- update other side --- */
  578.             tabstate = ASCII_SIDE;
  579.             compute_xy( &tmpx, &tmpy );
  580.             io_gotoxy( tmpx, tmpy );
  581.             io_putc( valid_char(buffer[bufpos]) );
  582.             tabstate = HEX_SIDE;
  583.  
  584.             io_gotoxy( curx, cury );
  585.             io_putc( keyhit );
  586.             do_right();
  587.  
  588.          }
  589.        }
  590.        else  /* --- Ascii side, allow regular characters --- */
  591.        {
  592.           buffer[bufpos] = (char)keyhit;
  593.  
  594.           /* --- Update other side --- */
  595.           tabstate = HEX_SIDE;
  596.           compute_xy( &tmpx, &tmpy );
  597.           io_gotoxy( tmpx, tmpy );
  598.           io_printf( "%02s", get_hex( (char)keyhit ) );
  599.           tabstate = ASCII_SIDE;
  600.  
  601.           io_gotoxy( curx, cury );
  602.           io_putc( valid_char((char)keyhit) );
  603.           do_right();
  604.  
  605.        }
  606.  
  607.  
  608.      }
  609.      else
  610.      {
  611.        ;
  612.      }
  613.   }
  614.   flush_buffer();
  615.  
  616.   fclose( file );
  617.  
  618.   return 1;
  619. }
  620.  
  621. void  refresh_screen( short firstrow, short lastrow ) 
  622. {
  623.   short y, i, j, k;
  624.   char hex_text[81] =   "                                        "
  625.                         "                                        ";
  626.   char ascii_text[81] = "                                        "
  627.                         "                                        ";
  628.   short bufidx = 0;
  629.   char ch;
  630.  
  631.   hex_text[HEX_LEN+1] = '\0';
  632.   ascii_text[ASCII_LEN] = '\0';
  633.  
  634.   for( y = firstrow, bufidx = (firstrow-STARTROW)*BYTES_PER_ROW;
  635.        y <= lastrow;  y++, bufidx+=BYTES_PER_ROW )
  636.   {
  637.      /* --- build hex/ascii -number text for display --- */
  638.      for ( i = bufidx, j=0, k=0;
  639.            i < bufidx + BYTES_PER_ROW && i < buflen; i++, j++, k+=2 )
  640.      {
  641.        ch = buffer[i];
  642.        /* --- hex number --- */
  643.        strncpy(&hex_text[k], get_hex(ch), 2 );
  644.        if ( (i+1) % 4 == 0 )
  645.        {
  646.          hex_text[k+2] = ' ';
  647.          k++;
  648.        }
  649.  
  650.        /* --- ascii number --- */
  651.        ascii_text[j] = valid_char( ch );
  652.  
  653.      }
  654.  
  655.      if ( hex_text[0] != ' ')
  656.        for ( i = k; i < HEX_LEN; i++ ) hex_text[i] = ' ';
  657.      for ( i = j; i < ASCII_LEN; i++ ) ascii_text[i] = ' ';
  658.  
  659.      /* --- Display the row --- */
  660.  
  661.      io_gotoxy( HEX_COL_START, y );
  662.      io_puts( hex_text );
  663.      io_puts( ascii_text );
  664.   }
  665. }
  666.  
  667. void flush_buffer( void )
  668. {
  669.      char tmp[100];
  670.      short keyhit;
  671.      short status;
  672.  
  673.      /* --- Check for changes to buffer --- */
  674.      if ( !read_only && orig_filepos >= 0L &&
  675.           memcmp( orig_buffer, buffer, buflen ) != 0 )
  676.      {
  677.         while( 1 )
  678.         {
  679.           io_gotoxy( 1, 2 );
  680.           sprintf( tmp, "Write changes?: Yes No  " );
  681.           io_printf( "%-79.79s", tmp );
  682.           io_gotoxy( strlen( tmp ), 2 );
  683.           io_refresh();
  684.  
  685.           keyhit = io_inchar( );
  686.  
  687.           if ( keyhit == 'Y' || keyhit == 'y' )  
  688.           {
  689.             /* --- write changes to the file --- */
  690.             fseek( file, orig_filepos, SEEK_SET );
  691.             status = fwrite( buffer, (size_t)buflen, (size_t)1, file );
  692.             if ( !status )
  693.             {
  694.                message( "Unable to write changes.  Hit a key..." );
  695.                memcpy( buffer, orig_buffer, buflen );
  696.             }
  697.             break;
  698.           }
  699.           else if ( keyhit == 'N' || keyhit == 'n' )
  700.           {
  701.              break;
  702.           }
  703.           else if ( keyhit == '?' )
  704.           {
  705.             do_help( write_changes_help );
  706.           }
  707.           else 
  708.           {
  709.             ;
  710.           }
  711.         } /* End while loop */
  712.  
  713.         io_gotoxy( 1, 2 );
  714.         io_printf("[ENTER]=Menu %65.65s", " " );
  715.      }
  716.  
  717. }
  718.  
  719. int  get_buffer( void )
  720. {
  721.      short status;
  722.  
  723.      flush_buffer();
  724.  
  725.      /* -- Always get end-of-file in case file length changes while editing -*/
  726.      get_file_length();
  727.  
  728.      if ( filelen < 1 )
  729.      {
  730.        message("Nothing in file!  Hit a key...");
  731.        return (-1);
  732.      }
  733.  
  734.      if ( filepos >= filelen )
  735.         filepos = filelen-1L;
  736.  
  737.      if ( filepos < 0L ) filepos = 0L;
  738.  
  739.      if ( BYTES_PER_PAGE < filelen - filepos  )
  740.        buflen = BYTES_PER_PAGE;
  741.      else
  742.        buflen = filelen - filepos;
  743.  
  744.      /* -- Clear out keyboard buffer before performing a disk read -- */
  745.      io_flush_keyboard();
  746.  
  747.       fseek( file, filepos, SEEK_SET );
  748.       status = fread( buffer, 1, buflen, file );
  749.       if ( !status )
  750.       {
  751.         message( "Unable to read file.  Hit a key..." );
  752.         memset( buffer, '\0', buflen );
  753.         filepos = 0L;
  754.         return (-1);
  755.       }
  756.  
  757.       if ( !read_only )
  758.       {
  759.         memcpy( orig_buffer, buffer, buflen );
  760.         orig_filepos = filepos;
  761.       }
  762.       return 0;
  763. }
  764.  
  765. void compute_xy( short *x, short *y ) 
  766. {
  767.    /* tabstate 0 means hex area
  768.    ** tabstate other means ascii area
  769.    */
  770.    short ascii_col_start = 56;
  771.    short hex_col_start   =  1;
  772.    short col_adder       = 0;
  773.  
  774.    if ( bufpos > buflen ) bufpos = buflen;
  775.  
  776.    if ( tabstate == ASCII_SIDE ) /* --- Ascii area --- */
  777.    {
  778.       *y = (bufpos / ASCII_LEN);
  779.       *x = (bufpos - (*y * BYTES_PER_ROW ) ) + ascii_col_start;
  780.       *y = *y + STARTROW;
  781.    }
  782.    else   /* --- Hex area --- */
  783.    {
  784.       *y = (bufpos / ASCII_LEN);
  785.       *x = (bufpos - (*y * BYTES_PER_ROW ) ); 
  786.       *y = *y + STARTROW;
  787.       col_adder = *x / 4;
  788.       *x = (*x * 2) + col_adder + nibblestate + hex_col_start;
  789.    }
  790.  
  791. }
  792.  
  793. void print_filename( void )
  794. {
  795.   char *ptr;
  796.  
  797.   /* ------------------------------- **
  798.   **   Print filename on header      **
  799.   ** ------------------------------- */
  800.  
  801.   io_gotoxy( 1, 1 );
  802.   ptr = strrchr( filename, '/' );
  803.   if ( ptr == (char *)0 )
  804.   {
  805.      ptr = strrchr( filename, '\\' );
  806.   }
  807.  
  808.   if ( ptr == (char *)0 )
  809.   {
  810.     io_printf( "%-24.24s", filename );
  811.   }
  812.   else
  813.   {
  814.     io_printf( "%-24.24s", &ptr[1] );
  815.   }
  816.  
  817. }
  818.  
  819. void update_position_display( void )
  820. {
  821.    char tmp[30];
  822.    long offset;
  823.  
  824.    offset = filepos + bufpos;
  825.    io_gotoxy( 54, 1 );
  826.    sprintf( tmp, "%ld, 0x%s", offset, long_to_hex( offset ) );
  827.    io_printf( "%-24s", tmp );
  828.  
  829. }
  830.  
  831. void do_page_up( long newbufpos )   
  832. {
  833.      if ( newbufpos < 0L ) newbufpos = 0L;
  834.      filepos -= BYTES_PER_PAGE;                              
  835.      if (filepos < 0L) filepos = 0L;                           
  836.      bufpos = 0L;                                             
  837.      get_buffer();                                           
  838.      refresh_screen( STARTROW, MAXROW );                     
  839.      if ( (newbufpos) > buflen - 1L )                         
  840.         bufpos = buflen - 1L;                                 
  841.      else                                                    
  842.         bufpos = (newbufpos);
  843.  
  844.      if ( bufpos < 0L ) bufpos = 0L;
  845. }
  846.  
  847. void do_page_down( long newbufpos )  
  848. {                                                          
  849.     if ( filepos + BYTES_PER_PAGE < filelen )               
  850.     {                                                       
  851.        filepos += BYTES_PER_PAGE;                           
  852.        if ( filepos > filelen ) filepos = filelen;          
  853.        bufpos = 0L;                                          
  854.        get_buffer();                                        
  855.        refresh_screen( STARTROW, MAXROW );                  
  856.        if ( (newbufpos) > buflen - 1L )                      
  857.             bufpos = buflen - 1L;                               
  858.        else                                                 
  859.             bufpos = (newbufpos);                              
  860.     }                                                       
  861. }
  862.  
  863. void do_right( void )
  864. {
  865.           if ( tabstate == ASCII_SIDE ) /* --- Ascii area --- */
  866.           {
  867.             if ( bufpos < buflen - 1 ) 
  868.                bufpos++;
  869.             else
  870.                do_page_down( 0 );
  871.           }
  872.           else   /* --- Hex text area --- */
  873.           {
  874.             if ( nibblestate == 0)
  875.             {
  876.               nibblestate = 1;
  877.             }
  878.             else
  879.             {
  880.               if ( bufpos < buflen - 1 )
  881.               {
  882.                  bufpos++;
  883.                  nibblestate = 0;
  884.               }
  885.               else
  886.                  do_page_down( 0 );
  887.             }
  888.           }
  889. }
  890.  
  891. /* --------------------------------- **
  892. **  M E N U   F U N C T I O N S      **
  893. ** --------------------------------- */
  894.  
  895. int do_menu( void )
  896. {
  897.    /* -- RETURN STATUS:  0 = continue normally, 1 = exit program --- */
  898.    short keyhit;
  899.    char  tmp[82];
  900.  
  901.    while( 1 )
  902.    {
  903.       io_gotoxy( 1, 2 );
  904.       sprintf( tmp, "Exit Goto Search Repeat_search Util re-Draw_screen Help  " );
  905.       io_printf( "%-79.79s", tmp );
  906.       io_gotoxy( strlen( tmp ), 2 );
  907.       io_refresh();
  908.  
  909.       keyhit = io_inchar( );
  910.  
  911.       if ( keyhit == 'E' || keyhit == 'e' )  /* -- Exit -- */
  912.       {
  913.          return 1;
  914.       }
  915.       else if ( keyhit == 'G' || keyhit == 'g' ) /* -- Goto -- */
  916.       {
  917.          do_goto_offset();
  918.          return 0;
  919.       }
  920.       else if ( keyhit == 'S' || keyhit == 's' )  /* -- Search -- */
  921.       {
  922.          do_search();
  923.          return 0;
  924.       }
  925.       else if ( keyhit == 'R' || keyhit == 'r' )  /* -- Repeat search -- */
  926.       {
  927.          do_repeat_search();
  928.          return 0;
  929.       }
  930.       else if ( keyhit == 'U' || keyhit == 'u' )  /* -- Utilities -- */
  931.       {
  932.          do_utilities();
  933.          return 0;
  934.       }
  935.       else if ( keyhit == 'D' || keyhit == 'd' )  /* -- re-draw screen -- */
  936.       {
  937.          /* --- Redraw screen -- */
  938.          display_header();
  939.          update_position_display();
  940.          print_filename();
  941.          get_file_length();
  942.          refresh_screen( STARTROW, MAXROW );
  943.          return 0;
  944.       }
  945.       else if ( keyhit == 'H' || keyhit == 'h' )  /* -- Help -- */
  946.       {
  947.          do_help( cursor_help );
  948.          return 0;
  949.       }
  950.       else if ( keyhit == '?' )
  951.       {
  952.          do_help( main_menu_help );
  953.       }
  954.       else if ( keyhit == io_ESCAPE || keyhit == io_ENTER ||
  955.                 keyhit == io_CTRL_M || keyhit == io_CTRL_C )
  956.       {
  957.          return 0;
  958.       }
  959.       else
  960.       {
  961.          ;
  962.       }
  963.    } /* End while loop */
  964. }
  965.  
  966. void do_goto_offset( void )
  967. {
  968.    short keyhit;
  969.    char tmp[100];
  970.    char tmp2[20];
  971.    unsigned long offset;
  972.  
  973.    while( 1 )
  974.    {
  975.       io_gotoxy( 1, 2 );
  976.       sprintf( tmp, "Enter offset# to go:  " );
  977.       io_printf( "%-79.79s", tmp );
  978.       io_gotoxy( strlen( tmp ), 2 );
  979.  
  980.       io_refresh();
  981.  
  982.       tmp2[0] = (char)0;                   
  983.       keyhit = input_line( tmp2, strlen( tmp ), 2, 15, 1, (int *)0, "" );
  984.  
  985.       if ( keyhit == io_ESCAPE || keyhit == io_CTRL_C ) return;
  986.  
  987.       if ( keyhit != io_ENTER && keyhit != io_CTRL_M && ( keyhit < 32 ||
  988.            keyhit > io_MAX_VALID_CHARACTER ) ) continue;
  989.  
  990.       rstrip(tmp2);
  991.       if ( strcmp( tmp2, "" ) == 0 ) return;
  992.  
  993.       if ( strcmp( tmp2, "?" ) == 0 )
  994.       {
  995.         do_help( offset_num_help );
  996.         continue;
  997.       }
  998.  
  999.       strip(tmp2);
  1000.       if ( strcmp( tmp2, "" ) == 0 ) return;
  1001.  
  1002.       if ( (int)strlen(tmp2) > (int)2 && tmp2[0] == '0' && tmp2[1] == 'X' )
  1003.       /* -- Hex value entered -- */
  1004.       {
  1005.          if ( hex_to_long( &tmp2[2], &offset ) == FALSE ) continue;
  1006.       }
  1007.       else  /* -- Numeric value entered -- */
  1008.       {
  1009.          offset = atol( tmp2 );
  1010.          if ( offset == 0 && strcmp( tmp2, "0" ) != 0 ) continue;
  1011.       }
  1012.       break;
  1013.    }
  1014.  
  1015.    filepos = offset;
  1016.    bufpos = 0;
  1017.  
  1018.    get_file_length();
  1019.  
  1020.    if ( filepos >= filelen )
  1021.    {
  1022.        filepos = filelen - BYTES_PER_PAGE + BYTES_PER_ROW;
  1023.        bufpos = filelen - filepos -1L;
  1024.    }
  1025.  
  1026.    if ( filepos < 0L )
  1027.    {
  1028.      filepos = 0L;
  1029.      bufpos = 0L;
  1030.    }
  1031.  
  1032.    get_buffer();
  1033.    refresh_screen( STARTROW, MAXROW );
  1034. }
  1035.  
  1036. void do_search( void )
  1037. {
  1038.    short keyhit;
  1039.    char tmp[82];
  1040.    char tmp2[82];
  1041.    char *ptr;
  1042.    short tmp_hex_len, i, j;
  1043.  
  1044.    /* ---- Get search direction ---- */
  1045.    while( 1 )
  1046.    {
  1047.       io_gotoxy( 1, 2 );
  1048.  
  1049.       sprintf( tmp, "search direction: Forward Backward  " );
  1050.  
  1051.       io_printf( "%-79.79s", tmp );
  1052.       io_gotoxy( strlen( tmp ), 2 );
  1053.       io_refresh();
  1054.  
  1055.       keyhit = io_inchar( );
  1056.  
  1057.       if ( keyhit == 'F' || keyhit == 'f' )  
  1058.       {
  1059.          search_direction = 'F';
  1060.          break;
  1061.       }
  1062.       else if ( keyhit == 'B' | keyhit == 'b' )
  1063.       {
  1064.          search_direction = 'B';
  1065.          break;
  1066.       }
  1067.       else if ( keyhit == '?' )
  1068.       {
  1069.         do_help( search_direction_help );
  1070.       }
  1071.  
  1072.       else if ( keyhit == io_ESCAPE || keyhit == io_ENTER || 
  1073.                 keyhit == io_CTRL_M || keyhit == io_CTRL_C )
  1074.       {
  1075.          return;
  1076.       }
  1077.       else
  1078.       {
  1079.          ;
  1080.       }
  1081.    } /* End while loop */
  1082.  
  1083.  
  1084.    /* ---- Get search type ---- */
  1085.    while( 1 )
  1086.    {
  1087.       io_gotoxy( 1, 2 );
  1088.  
  1089.       sprintf( tmp, "search type: Hex Ascii_text  " );
  1090.  
  1091.       io_printf( "%-79.79s", tmp );
  1092.       io_gotoxy( strlen( tmp ), 2 );
  1093.       io_refresh();
  1094.  
  1095.       keyhit = io_inchar( );
  1096.  
  1097.       if ( keyhit == 'H' || keyhit == 'h' )  
  1098.       {
  1099.          search_type = 'H';
  1100.          break;
  1101.       }
  1102.       else if ( keyhit == 'A' | keyhit == 'a' )
  1103.       {
  1104.          search_type = 'A';
  1105.          break;
  1106.       }
  1107.       else if ( keyhit == '?' )
  1108.       {
  1109.          do_help( search_type_help );
  1110.       }
  1111.       else if ( keyhit == io_ESCAPE || keyhit == io_ENTER || 
  1112.                 keyhit == io_CTRL_M || keyhit == io_CTRL_C )
  1113.       {
  1114.          return;
  1115.       }
  1116.       else
  1117.       {
  1118.          ;
  1119.       }
  1120.    } /* End while loop */
  1121.  
  1122.  
  1123.    /* --- Get search data --- */
  1124.    while( 1 )
  1125.    {
  1126.      switch ( search_type )
  1127.      {
  1128.        case 'A':
  1129.          io_gotoxy( 1, 2 );
  1130.  
  1131.          sprintf( tmp, "search string:  " );
  1132.  
  1133.          io_printf( "%-79.79s", tmp );
  1134.          io_gotoxy( strlen( tmp ), 2 );
  1135.          io_refresh();
  1136.  
  1137.          search_string[0] = (char)0;                   
  1138.          keyhit = input_line( search_string, strlen( tmp ), 2,
  1139.                               80 - strlen( tmp ), 1, (int *)0, "" );
  1140.  
  1141.          if ( keyhit == io_ESCAPE || keyhit == io_CTRL_C ) return;
  1142.          if ( keyhit != io_ENTER && keyhit != io_CTRL_M && ( keyhit < 32 ||
  1143.               keyhit > io_MAX_VALID_CHARACTER ) ) continue;
  1144.  
  1145.          lstrip( search_string );
  1146.          rstrip( search_string );
  1147.  
  1148.          if ( strcmp( search_string, ""  ) == 0 ) return;
  1149.          if ( strcmp( search_string, "?" ) == 0 )
  1150.          {
  1151.            do_help( search_string_help );
  1152.            continue;
  1153.          }
  1154.  
  1155.          search_string_len = strlen( search_string );
  1156.          break;
  1157.  
  1158.        case 'H':
  1159.          io_gotoxy( 1, 2 );
  1160.  
  1161.          sprintf( tmp, "search hex nums: " );
  1162.  
  1163.          io_printf( "%-79.79s", tmp );
  1164.          io_gotoxy( strlen( tmp ), 2 );
  1165.          io_refresh();
  1166.  
  1167.          tmp2[0] = (char)0;                   
  1168.          keyhit = input_line( tmp2, strlen( tmp ), 2, 80 - strlen( tmp ),
  1169.                               1, (int *)0, "" );
  1170.  
  1171.          if ( keyhit == io_ESCAPE || keyhit == io_CTRL_C ) return;
  1172.          if ( keyhit != io_ENTER && keyhit != io_CTRL_M && ( keyhit < 32 ||
  1173.               keyhit > io_MAX_VALID_CHARACTER ) ) continue;
  1174.  
  1175.          if ( strcmp( tmp2, "" ) == 0 ) return;
  1176.          if ( strcmp( tmp2, "?" ) == 0 )
  1177.          {
  1178.             do_help( search_hex_nums_help );
  1179.             continue;
  1180.          }
  1181.  
  1182.          /* --- convert this input to the search_string --- */
  1183.          strip( tmp2 );
  1184.          strcpy( search_string, "" );
  1185.   
  1186.          /* --- Strip off any leading 0x prefix --- */
  1187.          while(1)
  1188.          {
  1189.            ptr = strstr( tmp2, "0X" );
  1190.            if ( ptr == (char *)0 ) break;
  1191.            ptr[0] = ' ';
  1192.            ptr[1] = ' ';
  1193.          }
  1194.          strip( tmp2 );
  1195.          ptr = &tmp2[0];
  1196.  
  1197.          tmp_hex_len = strlen( ptr );
  1198.          if ( tmp_hex_len % 2 != 0 )
  1199.          {
  1200.             message( "Must enter an even number of hex values.  "
  1201.                      "Hit a key..." );
  1202.             continue;
  1203.          }
  1204.  
  1205.          search_string_len = tmp_hex_len / 2;
  1206.  
  1207.          /* --- Cycle through list of hex values --- */
  1208.          for ( i = 0, j=0; i < tmp_hex_len; i += 2, j++ )
  1209.          {
  1210.            search_string[j] = ( hex_to_nibble( ptr[i] ) << 4 ) | 
  1211.                                 hex_to_nibble( ptr[i+1] );
  1212.          }
  1213.          break;
  1214.  
  1215.      default:
  1216.        return;
  1217.      } /* -- End switch -- */
  1218.  
  1219.      break;
  1220.  
  1221.    } /* -- End while loop -- */
  1222.  
  1223.    /* --- Perform actual search --- */
  1224.    search_file( filepos + bufpos );
  1225. }
  1226.  
  1227. void do_repeat_search( void )
  1228. {
  1229.  
  1230.    /* --- Perform actual search --- */
  1231.    if ( search_direction == 'F' )
  1232.       search_file( filepos + bufpos + 1L);
  1233.    else
  1234.       search_file( filepos + bufpos - 1L);
  1235. }
  1236.  
  1237. void do_utilities( void )
  1238. {
  1239.    short keyhit;
  1240.    char tmp[82];
  1241.    char tmp2[82];
  1242.    char *ptr;
  1243.    short tmp_hex_len, i, j;
  1244.  
  1245.    /* ---- Utility Menu  ---- */
  1246.    while( 1 )
  1247.    {
  1248.       io_gotoxy( 1, 2 );
  1249.  
  1250.       sprintf( tmp, "util: Expand_file Save_chunk Hex_conv Calc "  );
  1251.  
  1252.       io_printf( "%-79.79s", tmp );
  1253.       io_gotoxy( strlen( tmp ), 2 );
  1254.       io_refresh();
  1255.  
  1256.       keyhit = io_inchar( );
  1257.  
  1258.       if ( toupper(keyhit) == 'E' )  /* -- expand file size -- */
  1259.       {
  1260.          do_setfilesize();
  1261.          break;
  1262.       }
  1263.       else if ( toupper(keyhit) == 'S' ) /* copy from this file to another */
  1264.       {
  1265.          do_savechunk();
  1266.          break;
  1267.       }
  1268.       else if ( toupper(keyhit) == 'H' ) /* --- Hex conversion stuff --- */
  1269.       {
  1270.          do_hexconv();
  1271.       }
  1272.       else if ( toupper(keyhit) == 'C' ) /* --- Calculator --- */
  1273.       {
  1274.          calc(4, 4);
  1275.          refresh_screen( 4, 16 );
  1276.       }
  1277.       else if ( keyhit == '?' )
  1278.       {
  1279.         do_help( util_help );
  1280.       }
  1281.  
  1282.       else if ( keyhit == io_ESCAPE || keyhit == io_ENTER || 
  1283.                 keyhit == io_CTRL_M || keyhit == io_CTRL_C )
  1284.       {
  1285.          return;
  1286.       }
  1287.       else
  1288.       {
  1289.          ;
  1290.       }
  1291.    } /* End while loop */
  1292.  
  1293. }
  1294.  
  1295. void do_setfilesize()
  1296. {
  1297.    short keyhit;
  1298.    char tmp[82];
  1299.    char z_newsize[80];
  1300.    unsigned long l_newsize;
  1301.    int status;
  1302.  
  1303.    /* ---- Get new filesize number  ---- */
  1304.    while( 1 )
  1305.    {
  1306.       io_gotoxy( 1, 2 );
  1307.  
  1308.       sprintf( tmp, "Enter new filesize, [ENTER] to cancel:  " );
  1309.  
  1310.       io_printf( "%-79.79s", tmp );
  1311.       io_gotoxy( strlen( tmp ), 2 );
  1312.       io_refresh();
  1313.  
  1314.       z_newsize[0] = (char)0;
  1315.       keyhit = input_line( z_newsize, strlen( tmp ), 2,
  1316.                               80 - strlen( tmp ), 1, (int *)0, ".NUMERIC" );
  1317.  
  1318.       if ( keyhit == io_ESCAPE || keyhit == io_CTRL_C ) return;
  1319.       if ( keyhit != io_ENTER && ( keyhit < 32 ||
  1320.            keyhit > io_MAX_VALID_CHARACTER ) && keyhit != io_CTRL_M ) continue;
  1321.  
  1322.       lstrip( z_newsize );
  1323.       rstrip( z_newsize );
  1324.  
  1325.       if ( strlen( z_newsize ) == 0 ) return;
  1326.  
  1327.       l_newsize = atol( z_newsize );
  1328.       if ( l_newsize <= filelen )
  1329.       {
  1330.         message( "New size must be larger than current size.  Hit a key...");
  1331.         continue;
  1332.       }
  1333.  
  1334.       fseek( file, l_newsize-1U, SEEK_SET );  
  1335.       status = fwrite( "\0", (size_t)1, (size_t)1, file );
  1336.       if ( !status )
  1337.       {
  1338.          message( "Unable to expand file.  Hit a key...");
  1339.          break;
  1340.       }
  1341.       fseek( file, filepos, SEEK_SET );
  1342.       get_buffer();
  1343.       refresh_screen( STARTROW, MAXROW );
  1344.       break;
  1345.    }
  1346.    return;
  1347. }
  1348.  
  1349. void do_savechunk( void )
  1350. {
  1351.    short keyhit;
  1352.    char tmp[82];
  1353.    char tmp2[80];
  1354.    char new_filename[200];
  1355.    unsigned long offset1, offset2;
  1356.    int status;
  1357.    FILE *newfile;
  1358.    char append = 'N';
  1359.  
  1360.    /* ---- Get starting offset#  ---- */
  1361.    while( 1 )
  1362.    {
  1363.       io_gotoxy( 1, 2 );
  1364.  
  1365.       sprintf( tmp, "Enter start offset number, [ENTER] to cancel:  " );
  1366.  
  1367.       io_printf( "%-79.79s", tmp );
  1368.       io_gotoxy( strlen( tmp ), 2 );
  1369.       io_refresh();
  1370.  
  1371.       tmp2[0] = (char)0;                   
  1372.       keyhit = input_line( tmp2, strlen( tmp ), 2,
  1373.                               80 - strlen( tmp ), 1, (int *)0, "" );
  1374.  
  1375.       if ( keyhit == io_ESCAPE || keyhit == io_CTRL_C ) return;
  1376.       if ( keyhit != io_ENTER && ( keyhit < 32 ||
  1377.            keyhit > io_MAX_VALID_CHARACTER ) && keyhit != io_CTRL_M ) continue;
  1378.  
  1379.       strip( tmp2 );
  1380.  
  1381.       if ( strcmp( tmp2, "" ) == 0 ) return;
  1382.  
  1383.       if ( (int)strlen(tmp2) > (int)2 && tmp2[0] == '0' && tmp2[1] == 'X' )
  1384.       /* -- Hex value entered -- */
  1385.       {
  1386.          if ( hex_to_long( &tmp2[2], &offset1 ) == FALSE ) continue;
  1387.       }
  1388.       else  /* -- Numeric value entered -- */
  1389.       {
  1390.          offset1 = atol( tmp2 );
  1391.          if ( offset1 == 0 && strcmp( tmp2, "0" ) != 0 ) continue;
  1392.       }
  1393.  
  1394.       if ( offset1 >= filelen )
  1395.       {
  1396.         message( "Offset number must be less than file length.  Hit a key...");
  1397.         continue;
  1398.       }
  1399.  
  1400.       break;
  1401.    }
  1402.  
  1403.    /* ---- Get ending offset#  ---- */
  1404.    while( 1 )
  1405.    {
  1406.       io_gotoxy( 1, 2 );
  1407.  
  1408.       sprintf( tmp, "Enter ending offset number, [ENTER] to cancel:  " );
  1409.  
  1410.       io_printf( "%-79.79s", tmp );
  1411.       io_gotoxy( strlen( tmp ), 2 );
  1412.       io_refresh();
  1413.  
  1414.       tmp2[0] = (char)0;                   
  1415.       keyhit = input_line( tmp2, strlen( tmp ), 2,
  1416.                               80 - strlen( tmp ), 1, (int *)0, ".NUMERIC" );
  1417.  
  1418.       if ( keyhit == io_ESCAPE || keyhit == io_CTRL_C ) return;
  1419.       if ( keyhit != io_ENTER && ( keyhit < 32 ||
  1420.            keyhit > io_MAX_VALID_CHARACTER ) && keyhit != io_CTRL_M ) continue;
  1421.  
  1422.       strip( tmp2 );
  1423.  
  1424.       if ( strcmp( tmp2, "" ) == 0 ) return;
  1425.  
  1426.       if ( (int)strlen(tmp2) > (int)2 && tmp2[0] == '0' && tmp2[1] == 'X' )
  1427.       /* -- Hex value entered -- */
  1428.       {
  1429.          if ( hex_to_long( &tmp2[2], &offset2 ) == FALSE) continue;
  1430.       }
  1431.       else  /* -- Numeric value entered -- */
  1432.       {
  1433.          offset2 = atol( tmp2 );
  1434.          if ( offset2 == 0 && strcmp( tmp2, "0" ) != 0 ) continue;
  1435.       }
  1436.  
  1437.       if ( offset2 >= filelen )
  1438.       {
  1439.         message( "Offset number must be less than file length.  Hit a key...");
  1440.         continue;
  1441.       }
  1442.       if ( offset2 < offset1 )
  1443.       {
  1444.         message( "Ending offset # can't be less than starting #.  Hit a key...");
  1445.         continue;
  1446.       }
  1447.       break;
  1448.    }
  1449.  
  1450.    /* ---- Get new filename  ---- */
  1451.    while( 1 )
  1452.    {
  1453.       append = 'N';
  1454.       io_gotoxy( 1, 2 );
  1455.  
  1456.       sprintf( tmp, "Enter new file name, [ENTER] to cancel:  " );
  1457.  
  1458.       io_printf( "%-79.79s", tmp );
  1459.       io_gotoxy( strlen( tmp ), 2 );
  1460.       io_refresh();
  1461.  
  1462.       new_filename[0] = (char)0;                   
  1463.       keyhit = input_line( new_filename, strlen( tmp ), 2,
  1464.                               80 - strlen( tmp ), 1, (int *)0, "" );
  1465.  
  1466.       if ( keyhit == io_ESCAPE || keyhit == io_CTRL_C ) return;
  1467.       if ( keyhit != io_ENTER && ( keyhit < 32 ||
  1468.            keyhit > io_MAX_VALID_CHARACTER ) && keyhit != io_CTRL_M ) continue;
  1469.  
  1470.       lstrip( new_filename );
  1471.       rstrip( new_filename );
  1472.  
  1473.       if ( strlen( new_filename ) == 0 ) return;
  1474.       if ( files_are_same( new_filename, filename ) )
  1475.       {
  1476.         message("New and current filenames should be different."
  1477.                 "  Hit a key...");
  1478.         continue;
  1479.       }
  1480.  
  1481.       newfile = fopen(new_filename,"rb");
  1482.       if ( newfile != (FILE *)0 )
  1483.       {
  1484.          fclose(newfile);
  1485.          io_gotoxy( 1, 2 );
  1486.          sprintf( tmp, "File exists:  Overwrite Append Cancel "  );
  1487.  
  1488.          io_printf( "%-79.79s", tmp );
  1489.          io_gotoxy( strlen( tmp ), 2 );
  1490.          io_refresh();
  1491.  
  1492.          keyhit = io_inchar( );
  1493.  
  1494.          if ( toupper(keyhit) == 'O')
  1495.          {
  1496.            append = 'N';
  1497.            io_unlink(new_filename);
  1498.            newfile = fopen(new_filename, "w+b");
  1499.          }
  1500.          else if ( toupper(keyhit) == 'A' )
  1501.          {
  1502.            append = 'Y';
  1503.            newfile = fopen(new_filename, "r+b");
  1504.          }
  1505.          else
  1506.          {
  1507.            continue;
  1508.          }
  1509.          
  1510.       }
  1511.       else
  1512.       {
  1513.         newfile = fopen(new_filename, "w+b");
  1514.       }
  1515.       if ( newfile == (FILE *)0 )
  1516.       {
  1517.         sprintf( tmp, "Can't update \"%1.30s\".  Hit a key...", new_filename );
  1518.         message( tmp );
  1519.         continue;
  1520.       }
  1521.  
  1522.       /*  Copy from "filename" to "newfile" starting from offset1 and
  1523.       **  ending at offset2
  1524.       */
  1525.  
  1526.       if ( copy_files( file, newfile, offset1, offset2, append ) == FALSE )
  1527.       {
  1528.          message("File-save aborted.  Hit a key...");
  1529.       }
  1530.  
  1531.       fclose(newfile);
  1532.       break;
  1533.    }
  1534.  
  1535.  
  1536.    return;
  1537.  
  1538. }
  1539.  
  1540. void  do_hexconv( void )
  1541. {
  1542.    char *hexscreen[] = {
  1543.      "   ________________________________________   ",
  1544.      "  |                                        |  ",
  1545.      "  | HEX  ........                          |  ",
  1546.      "  | DEC  ..........                        |  ",
  1547.      "  | BIN  ................................  |  ",
  1548.      "  | ASC  ....                              |  ",
  1549.      "  | ASC# ... ... ... ... <-ENTER=next byte |  ",
  1550.      "  |                                        |  ",
  1551.      "  | TAB=Next Field  ESC=Cancel             |  ",
  1552.      "  |________________________________________|  ",
  1553.      "                                              ",
  1554.      "\0"
  1555.    } ;
  1556.  
  1557.    char hex_str[9]  = "";
  1558.    char dec_str[11]   = "";
  1559.    char bin_str[33]  = "";
  1560.    char asc_str[5]   = "";
  1561.    char ascnum_str[4][4] = { "", "", "", "" };
  1562.  
  1563.    short i = 0;
  1564.    short oldi = 0;
  1565.    short field_num = 0;
  1566.    short col, row;
  1567.    long byte_len;
  1568.    long bitset;
  1569.    unsigned long dec = 0;
  1570.    char *options;
  1571.    short len;
  1572.    short ascpos = 0;
  1573.    int keyhit = 0;
  1574.  
  1575.    
  1576.    /* --- Display window  --- */
  1577.    while( strcmp( hexscreen[i], "\0" ) != 0 )
  1578.    {
  1579.       io_gotoxy( 11, STARTROW + i );
  1580.       io_printf( "%s", hexscreen[i] );
  1581.       i++;
  1582.    }
  1583.    io_refresh(); 
  1584.    col = 20;
  1585.  
  1586.    /* --- Prompt for value loop --- */
  1587.    while(1)
  1588.    {
  1589.   
  1590.       row = STARTROW + 2 + field_num;
  1591.       switch (field_num)
  1592.       {
  1593.         case 0: /* --- Hexadecimal --- */
  1594.           options = ".HEX .ZAP";
  1595.           len = 8;
  1596.           keyhit = input_line( hex_str, col, row, len, 1, (int *)0, options );
  1597.           hex_to_long( hex_str, &dec );
  1598.           break;
  1599.  
  1600.         case 1: /* --- Decimal --- */
  1601.           options = ".DEC .ZAP";
  1602.           len = 10;
  1603.           keyhit = input_line( dec_str, col, row, len, 1, (int *)0, options );
  1604.           dec = atol( dec_str );
  1605.           break;
  1606.  
  1607.         case 2: /* --- Binary --- */
  1608.           options = ".BIN .ZAP";
  1609.           len = 32;
  1610.           keyhit = input_line( bin_str, col, row, len, 1, (int *)0, options );
  1611.  
  1612.           /* -- convert binary string to a long (dec variable) -- */
  1613.           dec = 0L;
  1614.           bitset = 1L;
  1615.           for ( i = strlen(bin_str) - 1; i >= 0; i--)
  1616.           {
  1617.             if ( bin_str[i] == '1' )
  1618.             {
  1619.               dec = dec | bitset;
  1620.             }
  1621.             else
  1622.               if ( bin_str[i] != '0' ) break;
  1623.             bitset = bitset << 1;
  1624.           }
  1625.           break;
  1626.  
  1627.         case 3: /* --- ASCII --- */
  1628.           options = ".ZAP .PRE_VALIDATE";
  1629.           len = 4;
  1630.           keyhit = input_line( asc_str, col, row, len, 1, (int *)0, options );
  1631.  
  1632.           strcpy(hex_str,"");
  1633.           byte_len = strlen(asc_str);
  1634.           for ( i = 0; i < byte_len; i++)
  1635.           {
  1636.              strcat(hex_str, get_hex(asc_str[i]) );
  1637.           }
  1638.           hex_to_long(hex_str, &dec);
  1639.           break;
  1640.  
  1641.         case 4: /* --- ASCII # --- */
  1642.           options = ".NUMERIC .ZAP";
  1643.           len = 3;
  1644.  
  1645.             keyhit = input_line( &ascnum_str[ascpos][0],
  1646.                              col+(4*ascpos), row, len, 1, (int *)0, options );
  1647.  
  1648.             /* --- push everything over to left and clean up --- */
  1649.             for ( i = 0, oldi = 0; i <= 3; i++ )
  1650.             {
  1651.               strip(ascnum_str[i]);
  1652.               if ( strcmp( ascnum_str[i], "" ) == 0 ||
  1653.                    atoi(ascnum_str[i]) > 255 ||
  1654.                    atoi(ascnum_str[i]) < 0 )
  1655.               {
  1656.                 continue;
  1657.               }
  1658.               if ( i == oldi )
  1659.               {
  1660.                 oldi++;
  1661.                 continue;
  1662.               }
  1663.               strcpy(ascnum_str[oldi], ascnum_str[i]);
  1664.               oldi++;
  1665.             }
  1666.             for ( i = oldi; i <= 3; i++ )
  1667.             {
  1668.               strcpy( ascnum_str[i], "" );
  1669.             }
  1670.  
  1671.             /*
  1672.             **io_gotoxy( col+(4*ascpos), row );
  1673.             **io_printf( "%3s", ascnum_str[ascpos]);
  1674.             */
  1675.  
  1676.             /* --- Advance ascnum postion pointer --- */
  1677.             if ( keyhit == io_ENTER || keyhit == io_CTRL_M )
  1678.             {
  1679.                if ( ascpos < 3 )
  1680.                   ascpos++;
  1681.                else
  1682.                   ascpos = 0;
  1683.             }
  1684.             dec = 0L;
  1685.  
  1686.             /* --- Build long-integer dec --- */
  1687.             for ( i = 0; i <= 3; i++)
  1688.             {
  1689.               if ( strcmp( ascnum_str[i], "" ) == 0 ) break;
  1690.               if ( i != 0 ) dec = dec << 8;
  1691.               dec |= atol(ascnum_str[i]);
  1692.             }
  1693.  
  1694.           break;
  1695.  
  1696.         default:
  1697.           break;
  1698.       }
  1699.  
  1700.       if ( keyhit == io_ESCAPE || keyhit == io_CTRL_C ) break;
  1701.  
  1702.  
  1703.       /* --- Update all fields --- */
  1704.       /* dec must be set first */
  1705.  
  1706.       io_gotoxy(col, STARTROW+2);
  1707.       strcpy(hex_str,long_to_hex(dec));
  1708.       lstrip(hex_str);
  1709.       rstrip(hex_str);
  1710.       io_printf("%-10s", hex_str);
  1711.  
  1712.       io_gotoxy(col, STARTROW+2+1);
  1713.       sprintf(dec_str, "%-10lu", dec);
  1714.       io_puts(dec_str);
  1715.  
  1716.       io_gotoxy(col, STARTROW+2+2);
  1717.       strcpy( bin_str, long_to_bin(dec) );
  1718.       io_printf("%-32.32s", bin_str);
  1719.  
  1720.       io_gotoxy(col, STARTROW+2+3);
  1721.       io_printf( "....");
  1722.       io_gotoxy(col, STARTROW+2+4);
  1723.       io_printf( "... ... ... ...");
  1724.       strcpy( asc_str, hex_to_bytes(hex_str, &byte_len) );
  1725.       for ( i = 0; i < byte_len; i++)
  1726.       {
  1727.         io_gotoxy( col+i, STARTROW+2+3 );
  1728.         io_putc( valid_char( asc_str[i] ) );
  1729.         io_gotoxy( col+(i*4), STARTROW+2+4 );
  1730.         sprintf( ascnum_str[i], "%3hu", (unsigned short)asc_str[i] & 0x00FF );
  1731.         io_puts( ascnum_str[i] );
  1732.       }
  1733.  
  1734.       /* --- Check keystrokes --- */
  1735.       if ( keyhit == io_TAB || keyhit == io_CTRL_I || keyhit == io_DOWN
  1736.            || keyhit == io_CTRL_D )
  1737.       {
  1738.         if ( field_num < 4 )
  1739.           field_num++;
  1740.         else
  1741.           field_num = 0;
  1742.       }
  1743.       else if ( keyhit == io_UP || keyhit == io_CTRL_U )
  1744.       {
  1745.         if ( field_num > 0 )
  1746.           field_num--;
  1747.         else
  1748.           field_num = 4;
  1749.       }
  1750.  
  1751.    } /* End of while loop */
  1752.  
  1753. /* --- Done, refresh screen and exit --- */
  1754.     refresh_screen( STARTROW, STARTROW + 10 );
  1755. }
  1756.  
  1757. void do_help( char *help_text[] )
  1758. {
  1759.    short i = 0;
  1760.  
  1761.    while( strcmp( help_text[i], "\0" ) != 0 )
  1762.    {
  1763.       io_gotoxy( 11, STARTROW + i );
  1764.       io_printf( "%s", help_text[i] );
  1765.       i++;
  1766.    }
  1767.     io_refresh(); 
  1768.     (void)io_inchar();
  1769.     refresh_screen( STARTROW, STARTROW + i - 1 );
  1770. }
  1771.  
  1772. void  search_file( long start_pos )
  1773. {
  1774.    long old_file_pos, i, j;
  1775.    short old_buf_pos, match, count;
  1776.  
  1777.    old_file_pos = filepos;
  1778.    old_buf_pos = bufpos;
  1779.  
  1780.    /* --- last_search_pos hold current filepos --- */
  1781.    if ( start_pos > filelen )
  1782.    {
  1783.       message( "* End of file.  Hit a key.." );
  1784.       return;
  1785.    }
  1786.  
  1787.    filepos = start_pos;  /* Set to current cursor location */
  1788.    bufpos = 0L;
  1789.    count = 0;
  1790.  
  1791.    switch ( search_direction )
  1792.    {
  1793.      case 'F':  /* Forward */
  1794.        while( filepos < filelen )
  1795.        {
  1796.          io_gotoxy(60,2);      
  1797.          if( count > 60 )
  1798.          {
  1799.             io_printf("filepos: %10ld", filepos ); 
  1800.             count = 0;
  1801.          }
  1802.          else
  1803.          {
  1804.             count++;
  1805.          }
  1806.          io_refresh();
  1807.  
  1808.          get_buffer();
  1809.  
  1810.          /* --- Go through each position in the buffer --- */
  1811.          for ( i = 0; i < buflen; i++ )
  1812.          {
  1813.             /* --- Compare string with current string in buffer --- */
  1814.             match = 1;
  1815.             for ( j = 0; j < search_string_len; j++ )
  1816.             {
  1817.               if ( buffer[i+j] != search_string[j] )
  1818.               {
  1819.                 match = 0;
  1820.                 break;
  1821.               }
  1822.             }
  1823.             if ( match )
  1824.             {
  1825.               filepos += i;
  1826.               bufpos = 0;
  1827.               get_buffer();
  1828.               refresh_screen( STARTROW, MAXROW );
  1829.               /* message( "Match found.  Hit a key..." ); */
  1830.               refresh_screen( STARTROW, MAXROW );
  1831.               return;
  1832.             }
  1833.          }
  1834.          filepos += ( BYTES_PER_PAGE - search_string_len );
  1835.        } /* --- End of while loop -- */
  1836.  
  1837.        message( "No match found.  Hit a key..." );
  1838.        filepos = old_file_pos;
  1839.        bufpos = old_buf_pos;
  1840.        get_buffer();
  1841.        refresh_screen( STARTROW, MAXROW );
  1842.  
  1843.        break;
  1844.  
  1845.      case 'B':  /* Backward */
  1846.        while( filepos > 0L )
  1847.        {
  1848.          if ( filepos >= BYTES_PER_PAGE )
  1849.          {
  1850.             bufpos = BYTES_PER_PAGE;
  1851.            filepos -= (BYTES_PER_PAGE - search_string_len);
  1852.          }
  1853.          else
  1854.          {
  1855.             bufpos = filepos;
  1856.             filepos = 0L;
  1857.          }
  1858.  
  1859.          io_gotoxy(60,2);  
  1860.          io_printf("filepos: %10ld", filepos ); 
  1861.          io_refresh();
  1862.     
  1863.          get_buffer();
  1864.  
  1865.          /* --- Go through each position in the buffer --- */
  1866.          for ( i = buflen-1; i >= 0; i-- )
  1867.          {
  1868.             /* --- Compare string with current string in buffer --- */
  1869.             match = 1;
  1870.             for ( j = 0; j < search_string_len; j++ )
  1871.             {
  1872.               if ( buffer[i+j] != search_string[j] )
  1873.               {
  1874.                 match = 0;
  1875.                 break;
  1876.               }
  1877.             }
  1878.             if ( match )
  1879.             {
  1880.               filepos += i;
  1881.               bufpos = 0;
  1882.               get_buffer();
  1883.               refresh_screen( STARTROW, MAXROW );
  1884.             /* message( "Match found.  Hit a key..." ); */
  1885.               refresh_screen( STARTROW, MAXROW );
  1886.               return;
  1887.             }
  1888.          }
  1889.        } /* --- End of while loop -- */
  1890.  
  1891.        message( "No match found.  Hit a key..." );
  1892.        filepos = old_file_pos;
  1893.        bufpos = old_buf_pos;
  1894.        get_buffer();
  1895.        refresh_screen( STARTROW, MAXROW );
  1896.  
  1897.        break;
  1898.  
  1899.      default:
  1900.       ;
  1901.    }
  1902.  
  1903. }
  1904.  
  1905. void calc(short col, short row)
  1906. {
  1907.    /* --- Calculator variables -- */
  1908.    static char editstr[30] = "";
  1909.    char *sptr;
  1910.    short keyhit = 0, i = 0;
  1911.    char operator = ' ';
  1912.    char cur_oper = 1;
  1913.    long double max_num;
  1914.    short max_places = 18;
  1915.    short degrees = 1;
  1916.    short radians = 2;
  1917.    short grads   = 3;
  1918.    short start = 0;
  1919.    short deg_rad_grad = 1;
  1920.    long double pi = 3.141592653589793238462643383279;
  1921.    
  1922.  
  1923.    int exitlist[] = {
  1924.        io_LEFT, io_RIGHT, '-', '+', '*',
  1925.        '/', '^', ' ', '=', io_ENTER, io_CTRL_M, io_CTRL_L, io_CTRL_R,
  1926.        'Q', 'q', 'A', 'a', 'Z', 'z', 'W', 'w', 'S', 's',
  1927.        'X', 'x', 'E', 'e', 'D', 'd', 'C', 'c', 'R', 'r',
  1928.        'F', 'f', 'V', 'v', 'T', 't', 'G', 'g', 'B', 'b',
  1929.        'Y', 'y', 'H', 'h', 'N', 'n',
  1930.        0
  1931.     };
  1932.                 
  1933.    char status;
  1934.    long double operand[3];
  1935.  
  1936.    char *calc_screen[] = {
  1937.    "  ___________________________________________  ",
  1938.    " |                                           | ",
  1939.    " |                                           | ",
  1940.    " |  ------------------                       | ",
  1941.    " |                                           | ",
  1942.    " | Q:Clr  W:sin E:asin R:1/x   T:n!   Y:DRG  | ",
  1943.    " | A:ClrE S:cos D:acos F:log10 G:10^x H:pi   | ",
  1944.    " | Z:+/-  X:tan C:atan V:ln    B:e^x         | ",
  1945.    " |                                           | ",
  1946.    " | Digits 0-9, Operators +-*/^=              | ",
  1947.    " | ESC:Exit   ENTER:Equals                   | ",
  1948.    " |___________________________________________| ",
  1949.    "                                               ",
  1950.    "\0"
  1951.    };
  1952.  
  1953.    max_num = (long double)pow(10, max_places);
  1954.  
  1955.    for ( i = 0; i < 3; i++) operand[i] = 0;
  1956.  
  1957.    status = ' ';
  1958.    (void)calc_error("CLEAR");
  1959.  
  1960.    /* --- Begin calc code --- */
  1961.    io_flush_keyboard();
  1962.  
  1963.  
  1964.    /* -- Begin displaying the calculator -- */
  1965.    i = 0;
  1966.    while ( strcmp( calc_screen[i], "" ) != 0 )
  1967.    {
  1968.       io_gotoxy( col, row + i );
  1969.       io_puts( calc_screen[i] ); 
  1970.       i++;
  1971.    }
  1972.  
  1973.    while(1)
  1974.    {
  1975.      if ( calc_error("") == 1 ) status = 'E';
  1976.      /* --- Update screen --- */
  1977.      io_gotoxy(2+col, 2+row);
  1978.      io_printf("%c", status );
  1979.  
  1980.      io_gotoxy(2+max_places+4+col, 2+row);
  1981.      io_printf("%c", operator );
  1982.  
  1983.      io_gotoxy(2+max_places+4+3+col, 2+row);
  1984.      if ( degrees == deg_rad_grad )
  1985.          io_printf("DEG ");
  1986.      else if ( radians == deg_rad_grad )
  1987.          io_printf("RAD ");
  1988.      else if ( grads == deg_rad_grad )
  1989.          io_printf("GRAD");
  1990.      else
  1991.          ;
  1992.  
  1993.      /* Strip off trailing spaces */
  1994.      sptr = strchr( editstr, ' ');
  1995.      if ( sptr != (char *)0 ) sptr[0] = (char)0;
  1996.  
  1997.      if ( (long)strlen(editstr) >= (long)max_places )
  1998.        start = max_places;
  1999.      else
  2000.        start = strlen(editstr) + 1;
  2001.      
  2002.  
  2003.      io_refresh();
  2004.      /* --- Get keystroke --- */
  2005.      keyhit = input_line(editstr,
  2006.                        4+col,                /* Column */
  2007.                        2+row,                /* Row    */
  2008.                        max_places,           /* Length */
  2009.                        start,                /* startpos */
  2010.                        exitlist,             /* exitlist */
  2011.                        ".NUMERIC .ZAP"       /* options  */
  2012.                       );
  2013.  
  2014.      operand[cur_oper] = (long double)atof(editstr);
  2015.  
  2016.     
  2017.      if ( keyhit == io_ESCAPE )
  2018.      {
  2019.          break;
  2020.      }
  2021.  
  2022.      else if( keyhit == 'Q' || keyhit == 'q' ) /* Clear all   */
  2023.      {
  2024.          for ( i = 0; i < 3; i++) operand[i] = (long double)0;
  2025.          status = ' ';
  2026.          cur_oper = 1;
  2027.          operator = ' ';
  2028.          strcpy(editstr,"");
  2029.          (void)calc_error("CLEAR");
  2030.          continue;
  2031.      }
  2032.      else if( keyhit == 'A' || keyhit == 'a' ) /* Clear entry */
  2033.      {
  2034.          operand[cur_oper] = (long double)0;
  2035.          strcpy(editstr,"");
  2036.          status = ' ';
  2037.          (void)calc_error("CLEAR");
  2038.          continue;
  2039.      }
  2040.      else if(status == 'E' )  /* Error entry */
  2041.      {
  2042.        ; /* -- Will fall through to bottom -- */
  2043.      }  
  2044.      else if( keyhit == 'Z' || keyhit == 'z' ) /* +/-         */
  2045.      {
  2046.            operand[cur_oper] = operand[cur_oper] * (long double)-1;
  2047.      }
  2048.      else if( keyhit == 'W' || keyhit == 'w' ) /* sine        */
  2049.      {
  2050.            if ( degrees == deg_rad_grad )
  2051.              operand[cur_oper] = (long double)sin(operand[cur_oper] * pi / 180);
  2052.            else if ( radians == deg_rad_grad )
  2053.              operand[cur_oper] = (long double)sin(operand[cur_oper]);
  2054.            else if ( grads  == deg_rad_grad )  
  2055.              operand[cur_oper] = (long double)sin(operand[cur_oper] * pi / 200);
  2056.            else
  2057.              ;
  2058.      }
  2059.      else if( keyhit == 'S' || keyhit == 's' ) /* cosine      */
  2060.      {
  2061.            if ( degrees == deg_rad_grad )
  2062.              operand[cur_oper] = (long double)cos(operand[cur_oper] * pi / 180);
  2063.            else if ( radians == deg_rad_grad )
  2064.              operand[cur_oper] = (long double)cos(operand[cur_oper]);
  2065.            else if ( grads == deg_rad_grad )
  2066.              operand[cur_oper] = (long double)cos(operand[cur_oper] * pi / 200);
  2067.            else
  2068.              ;
  2069.      }
  2070.      else if( keyhit == 'X' || keyhit == 'x' ) /* tangent     */
  2071.      {
  2072.            if ( degrees == deg_rad_grad )
  2073.              operand[cur_oper] = (long double)tan(operand[cur_oper] * pi / 180);
  2074.            else if ( radians == deg_rad_grad )
  2075.              operand[cur_oper] = (long double)tan(operand[cur_oper]);
  2076.            else if ( grads == deg_rad_grad )
  2077.              operand[cur_oper] = (long double)tan(operand[cur_oper] * pi / 200);
  2078.            else
  2079.              ;
  2080.      }
  2081.      else if( keyhit == 'E' || keyhit == 'e' ) /* arcsine     */
  2082.      {
  2083.          
  2084.          if  ( fabs(operand[cur_oper]) > 1 )
  2085.          {
  2086.              status = 'E';
  2087.          }
  2088.          else if ( deg_rad_grad == degrees )
  2089.          {
  2090.              operand[cur_oper] = (long double)asin(operand[cur_oper]) *
  2091.                                  180 / pi;
  2092.          }
  2093.          else if ( deg_rad_grad == radians )
  2094.          {
  2095.              operand[cur_oper] = (long double)asin(operand[cur_oper]);
  2096.          }
  2097.          else if ( deg_rad_grad == grads )
  2098.          {
  2099.              operand[cur_oper] = (long double)asin(operand[cur_oper]) *
  2100.                                   200 / pi;
  2101.          }
  2102.          else
  2103.          { ; }
  2104.      }
  2105.      else if( keyhit == 'D' || keyhit == 'd' ) /* arccosine   */
  2106.      {
  2107.            if  ( fabs(operand[cur_oper]) > 1 )
  2108.            {
  2109.              status = 'E';
  2110.            }
  2111.            else if ( deg_rad_grad == degrees )
  2112.            {
  2113.              operand[cur_oper] = (long double)acos(operand[cur_oper]) *
  2114.                                  180 / pi;
  2115.            }
  2116.            else if ( deg_rad_grad == radians )
  2117.            {
  2118.              operand[cur_oper] = (long double)acos(operand[cur_oper]);
  2119.            }
  2120.            else if ( deg_rad_grad == grads )
  2121.            {
  2122.              operand[cur_oper] = (long double)acos(operand[cur_oper]) *
  2123.                                  200 / pi;
  2124.            }
  2125.            else
  2126.            {
  2127.              ;
  2128.            }
  2129.       }
  2130.       else if ( keyhit == 'C' || keyhit == 'c' ) /* arctangent  */
  2131.       {
  2132.          if ( deg_rad_grad == degrees )
  2133.          {
  2134.              operand[cur_oper] = (long double)atan(operand[cur_oper]) *
  2135.                                  180 / pi;
  2136.          }
  2137.          else if ( deg_rad_grad == radians )
  2138.          {
  2139.              operand[cur_oper] = (long double)atan(operand[cur_oper]);
  2140.          }
  2141.          else if ( deg_rad_grad == grads )
  2142.          {
  2143.              operand[cur_oper] = (long double)atan(operand[cur_oper]) *
  2144.                                  200 / pi;
  2145.          }
  2146.          else
  2147.          {
  2148.              ;
  2149.          }
  2150.       }
  2151.       else if ( keyhit == 'R' || keyhit == 'r' ) /* 1/x         */
  2152.       {
  2153.          if ( operand[cur_oper] == (long double)0 )
  2154.            status = 'E';
  2155.          else
  2156.            operand[cur_oper] = (long double)1 / operand[cur_oper];
  2157.          
  2158.       }
  2159.       else if( keyhit == 'F' || keyhit == 'f' ) /* log10       */
  2160.       {
  2161.          if ( operand[cur_oper] == (long double)0 )
  2162.            status = 'E';
  2163.          else
  2164.            operand[cur_oper] = (long double)log10(operand[cur_oper]);
  2165.          
  2166.       }
  2167.       else if ( keyhit == 'V' || keyhit == 'v' ) /* natural log */
  2168.       {
  2169.          if ( operand[cur_oper] == (long double)0 )
  2170.            status = 'E';
  2171.          else
  2172.            operand[cur_oper] = (long double)log(operand[cur_oper]);
  2173.          
  2174.       }
  2175.       else if ( keyhit == 'T' || keyhit == 't' ) /* factorial!  */
  2176.       {
  2177.          long double i = 0; long double sum = 1; long start = 0;
  2178.          start = operand[cur_oper];
  2179.          if ( start < 0 ) start = start * (long double)-1;
  2180.          start = floor(start);
  2181.  
  2182.          for ( i = start; i > 1; i-- )
  2183.          {
  2184.             sum = sum * i;
  2185.             if ( sum > max_num ) break;
  2186.          }
  2187.  
  2188.          operand[cur_oper] = sum;
  2189.       }
  2190.       else if ( keyhit == 'G' || keyhit == 'g' ) /* 10 ^ x      */
  2191.       {
  2192.          operand[cur_oper] = (long double)pow(10, operand[cur_oper]);
  2193.       }
  2194.       else if( keyhit == 'B' || keyhit == 'b' ) /* e  ^ x      */
  2195.       {
  2196.          operand[cur_oper] = (long double)exp(operand[cur_oper]);
  2197.       }   
  2198.       else if ( keyhit == 'Y' || keyhit == 'y' ) /* Degrees, Radians, Grads */
  2199.       {
  2200.          if ( deg_rad_grad < 3 )
  2201.            deg_rad_grad++;
  2202.          else
  2203.            deg_rad_grad = 1;
  2204.       }
  2205.       else if ( keyhit == 'H' || keyhit == 'h' ) /* pi          */
  2206.       {
  2207.          operand[cur_oper] = pi;
  2208.       }
  2209.       else if ( keyhit == 'N' || keyhit == 'n' ) /*             */
  2210.       {
  2211.          ;
  2212.       }
  2213.  
  2214.  
  2215.     /* ---- OPERATORS ---- */
  2216.  
  2217.       else if ( keyhit == '+' || keyhit == '-' || keyhit == '*' ||
  2218.               keyhit == '/' || keyhit == '^' || keyhit == '=' ||
  2219.               keyhit == io_ENTER
  2220.             )
  2221.       {
  2222.          if ( cur_oper == 2 )  /* --- Assign result to operand[1] --- */
  2223.          {
  2224.            switch (operator)
  2225.            {
  2226.              case '+':
  2227.                operand[1] = operand[1] + operand[2];
  2228.                break;
  2229.              case '-':
  2230.                operand[1] = operand[1] - operand[2];
  2231.                break;
  2232.              case '*':
  2233.                operand[1] = operand[1] * operand[2];
  2234.                break;
  2235.              case '/':
  2236.                if ( operand[2] == 0 )
  2237.                {
  2238.                  operand[1] = 0;
  2239.                  status = 'E';
  2240.                }
  2241.                else
  2242.                {
  2243.                  operand[1] = operand[1] / operand[2];
  2244.                }
  2245.                break;
  2246.              case  '^':
  2247.                operand[1] = (long double)pow(operand[1], operand[2]);
  2248.                break;
  2249.              default:
  2250.                ;
  2251.            }
  2252.          }  
  2253.  
  2254.          if ( keyhit == '+' || keyhit == '-' || keyhit == '*' ||
  2255.               keyhit == '/' || keyhit == '^'
  2256.             )
  2257.          {
  2258.            operand[2] = operand[1];
  2259.            operator = (char)keyhit;
  2260.            cur_oper = 2;
  2261.          }
  2262.          else
  2263.          {
  2264.            operator = ' ';
  2265.            cur_oper = 1;
  2266.          }      
  2267.       }
  2268.       else
  2269.       {
  2270.          continue;
  2271.       }
  2272.      
  2273.      /* --- Update the edit string --- */
  2274.      if ( fabs(operand[cur_oper]) >= max_num )
  2275.      {
  2276.        status = 'E';
  2277.        sprintf(editstr,"");
  2278.      }
  2279.      else
  2280.      {
  2281.        char *ptr = (char *)0;
  2282.        char *ptr2 = (char *)0;
  2283.        char *ptr3 = (char *)0;
  2284.  
  2285.        /* -- Compensate for rounding errors -- */
  2286.        if (operand[cur_oper] < 0)
  2287.        {
  2288.         ;
  2289.        }
  2290.        else
  2291.        {
  2292.          operand[cur_oper] = operand[cur_oper] +
  2293.           (  ((long double)1) / (long double)pow(10, max_places) );
  2294.        }
  2295.  
  2296.        /* -- Format number into string -- */
  2297.        sprintf(editstr,"%*.*Lf", max_places, max_places, operand[cur_oper]);
  2298.        editstr[max_places] = (char)0;
  2299.  
  2300.        /* -- strip off trailing zeros past the decimal place. -- */
  2301.        ptr = strchr(editstr,'.');
  2302.        ptr2 = strchr(editstr, '\0');
  2303.  
  2304.        if ( ptr != (char *)0 && ptr2 != (char *)0)
  2305.        {
  2306.          for ( ptr3 = ptr2-1; ptr3 != ptr; ptr3-- )
  2307.          {
  2308.             if ( ptr3[0] != '0' ) break;
  2309.          }
  2310.          if ( ptr3 == ptr )
  2311.          {
  2312.            ptr[0] = (char)0;  /* --- Get rid of decimal point if nothing
  2313.                                      is to its right --- */
  2314.          }
  2315.          else
  2316.          {
  2317.            ptr3[1] = (char)0;
  2318.          }     
  2319.        }     
  2320.      }      
  2321.    } 
  2322. }
  2323.  
  2324. int matherr(struct exception *x)
  2325. {
  2326.   (void)calc_error( "SET" );
  2327.   return 1; /* To prevent display of built-in error message */
  2328. }
  2329.  
  2330. int calc_error( char * action )
  2331. {
  2332.    static int math_error = 0;
  2333.    if ( strcmp(action, "SET") == 0 ) math_error = 1;
  2334.    if ( strcmp(action, "CLEAR") == 0 ) math_error = 0;
  2335.    return math_error;
  2336. }
  2337.  
  2338.  
  2339. /* ----------------------------------- **
  2340. **  U T I L I T Y   F U N C T I O N S  **
  2341. ** ----------------------------------- */
  2342.  
  2343. int copy_files( FILE *source, FILE *dest, long offset1, long offset2,
  2344.                 char append )
  2345. {
  2346.   /*
  2347.   ** Returns: FALSE if copy failed
  2348.   **          TRUE if copy succeeded
  2349.   **
  2350.   ** append: 'Y' means append to end of destination, otherwise overwrite
  2351.   */
  2352.  
  2353.   char *copy_buffer = (char *)0;
  2354.   unsigned long buffer_size = 0UL;
  2355.   unsigned long max_buffer_size = 100000UL;
  2356.   unsigned long copy_filepos = 0UL;
  2357.   int status = TRUE;
  2358.   unsigned long adder = 0UL;
  2359.  
  2360.   if ( offset2 - offset1 + 1L < 100000L )
  2361.   {
  2362.     max_buffer_size = offset2 - offset1 + 1UL;
  2363.   }
  2364.  
  2365.   while(1)
  2366.   {
  2367.     copy_buffer = (char *)malloc((size_t)max_buffer_size);
  2368.     if ( copy_buffer == ( char * )0 )
  2369.     {
  2370.        max_buffer_size /= 2L;
  2371.        if ( max_buffer_size < 10L ) return FALSE;
  2372.     }
  2373.     else
  2374.     {
  2375.       break;
  2376.     }
  2377.   }
  2378.  
  2379.   buffer_size = max_buffer_size;
  2380.   if ( append == 'Y' )
  2381.   {
  2382.     fseek( dest, 0L, SEEK_END );
  2383.     adder = ftell( dest );   /* Get file length */ 
  2384.   }
  2385.  
  2386.   for ( copy_filepos = offset1;
  2387.         copy_filepos <= offset2;
  2388.         copy_filepos += max_buffer_size
  2389.       )
  2390.   {
  2391.     if ( copy_filepos + max_buffer_size > offset2 )
  2392.     {
  2393.       buffer_size = offset2 - copy_filepos + 1UL;
  2394.     }
  2395.  
  2396.     errno = 0; 
  2397.     status = (int)fseek( source, copy_filepos, SEEK_SET );
  2398.     if ( status == -1 && errno )
  2399.     {
  2400.       status = FALSE;
  2401.       break;
  2402.     }
  2403.     errno = 0;
  2404.     status = (int)fseek( dest, copy_filepos - offset1 + adder, SEEK_SET );
  2405.     if ( status == -1 && errno)
  2406.     {
  2407.       status = FALSE;
  2408.       break;
  2409.     }
  2410.  
  2411.     status = fread( copy_buffer, (size_t)1, (size_t)buffer_size, source );
  2412.     if ( !status ) break;
  2413.     status = fwrite( copy_buffer, (size_t)1, (size_t)buffer_size, dest );
  2414.     if ( !status ) break;
  2415.   }
  2416.  
  2417.   fseek( file, filepos, SEEK_SET );
  2418.   free(copy_buffer);
  2419.   return status;
  2420. }
  2421.  
  2422. char *get_hex( char ch )
  2423. {
  2424.   /*
  2425.   ** Return the hex value in the form of a string
  2426.   */
  2427.   static char tmp[3] = {0,0,0};
  2428.   char lo, hi;
  2429.  
  2430.   lo = ch & 0x0F;
  2431.   hi = (ch >> 4) & 0x0F;
  2432.  
  2433.   if ( lo < 10 )
  2434.     tmp[1] = lo + (char)'0';
  2435.   else
  2436.     tmp[1] = lo + (char)'A' - 10;
  2437.  
  2438.   if ( hi < 10 )
  2439.     tmp[0] = hi + (char)'0';
  2440.   else
  2441.     tmp[0] = hi + (char)'A' - 10;
  2442.  
  2443.   return tmp;
  2444. }
  2445.  
  2446. void strip( char *s )
  2447. {
  2448.   long source=0, target=0, len=0;
  2449.  
  2450.   len = strlen( s );
  2451.   if ( len == 0 ) return;
  2452.  
  2453.   while( source < len )
  2454.   {
  2455.      if ( s[source] >= 'a' && s[source] <= 'z' ) 
  2456.      {
  2457.        s[source] = (char)toupper( s[source] );
  2458.      }
  2459.      if ( ( s[source] >= '0' && s[source] <= '9' ) ||
  2460.           ( s[source] >= 'A' && s[source] <= 'Z' )
  2461.         )
  2462.      {
  2463.        if ( source != target )
  2464.        {
  2465.          s[target] = s[source];
  2466.        } 
  2467.        target++;
  2468.      }
  2469.      source++;
  2470.   }
  2471.  
  2472.   s[target] = (char)0;
  2473. }
  2474.  
  2475. int hex_to_long( char *s, unsigned long *ret_val )
  2476. {
  2477.    /*
  2478.    ** Convert a hexadecimal number from string to long int
  2479.    ** Return value: FALSE = function failed
  2480.    **               TRUE  = function worked
  2481.    */
  2482.    long len, i;
  2483.    char ch;
  2484.  
  2485.    *ret_val = (unsigned long)0;
  2486.  
  2487.    len = strlen( s );
  2488.    if ( len > 8 ) return FALSE;
  2489.  
  2490.    for (i = 0; i < len; i++ )
  2491.    {
  2492.       ch = s[i];
  2493.       ch = (char)toupper( ch );
  2494.  
  2495.       if ( ch >= '0' && ch <= '9' )
  2496.       {
  2497.          *ret_val = ( *ret_val << 4 ) | (unsigned long)( ch - '0' );
  2498.       }
  2499.       else if ( ch >= 'A' && ch <= 'F' )
  2500.       {
  2501.          *ret_val = ( *ret_val << 4 ) | (unsigned long)( ch - 'A' + 10 );
  2502.       }
  2503.       else
  2504.       {
  2505.          return FALSE;
  2506.       }   
  2507.    }  
  2508.    return TRUE;
  2509. }
  2510.  
  2511. /* -- Converts written hex digit to nibble -- */
  2512. char hex_to_nibble( char c )
  2513. {
  2514.    char ch;
  2515.  
  2516.    ch = (char)toupper( c );
  2517.  
  2518.    if ( ch >= '0' && ch <= '9' )
  2519.    {
  2520.        return (char)( ch - '0' );
  2521.    }
  2522.    else if ( ch >= 'A' && ch <= 'F' )
  2523.    {
  2524.       return (char)( ch - 'A' + 10 );
  2525.    }
  2526.    else  /* --- Failure --- */
  2527.    {
  2528.       return 0xFF;
  2529.    }   
  2530. }
  2531.  
  2532. char *hex_to_bytes( char *hex, long *b_len)
  2533. {
  2534.   static char *s = (char *)0;
  2535.   char * hex_ptr;
  2536.   long hex_len, byte_len, i, j;
  2537.  
  2538.   if ( s != (char *)0 ) free (s);
  2539.   hex_len = strlen(hex);
  2540.   if ( hex_len > 1 )
  2541.   {
  2542.     if ( hex[0] == '0' && hex[1] == 'x' )
  2543.     {
  2544.       hex_ptr = &hex[2];
  2545.       hex_len = strlen(hex_ptr);
  2546.     }
  2547.     else
  2548.     {
  2549.       hex_ptr = hex;
  2550.     }
  2551.   }
  2552.   else
  2553.   {
  2554.     hex_ptr = hex;
  2555.   }
  2556.  
  2557.   byte_len = (hex_len / 2) + (hex_len % 2);
  2558.   s = (char *)malloc((size_t)(byte_len+1L));
  2559.   if ( s == (char *)0 ) return s;
  2560.   memset(s, '\0', (size_t)(byte_len + 1L));
  2561.  
  2562.   for ( i = byte_len-1, j = hex_len-1; i >= 0; i--, j-=2 )
  2563.   {
  2564.     s[i] = hex_to_nibble(hex_ptr[j]);
  2565.     if ( j > 0 ) s[i] = s[i] + (hex_to_nibble(hex_ptr[j-1]) << 4);
  2566.   }
  2567.  
  2568.   *b_len = byte_len;
  2569.   return s;
  2570. }
  2571.  
  2572.  
  2573. char *long_to_hex( long l )
  2574. {
  2575.   static char s[10];
  2576.   long source=0, target=0, len=0;
  2577.   short flag=0;
  2578.  
  2579.   strcpy( s,"" );
  2580.   strcat( s, get_hex( (char)(l >> 24) ) );
  2581.   strcat( s, get_hex( (char)((l >> 16) & 0x000000FF) ) );
  2582.   strcat( s, get_hex( (char)((l >> 8) & 0x000000FF) ) );
  2583.   strcat( s, get_hex( (char)(l & 0x000000FF) ) );
  2584.  
  2585.   /* --- clean off leading zeros --- */
  2586.   len = strlen( s );
  2587.   if ( len == 0 ) return (char *)0;
  2588.  
  2589.   while( source < len )
  2590.   {
  2591.      if ( flag )
  2592.      {
  2593.        if ( source != target )
  2594.        {
  2595.          s[target] = s[source];
  2596.        } 
  2597.        target++;
  2598.  
  2599.      }
  2600.      else
  2601.      {
  2602.        if ( s[source] != '0' )
  2603.        {
  2604.          flag = 1;
  2605.          source--;
  2606.        }
  2607.      }
  2608.      source++;
  2609.   }
  2610.  
  2611.   s[target] = (char)0;
  2612.   return s;
  2613. }
  2614.  
  2615. char *long_to_bin( long l )
  2616. {
  2617.   static char s[33];
  2618.   short i;
  2619.  
  2620.   s[32]=(char)0;
  2621.   for ( i = 1; i <= 32; i++)
  2622.   {
  2623.      if ( l & 0x0001 )
  2624.        s[32-i] = '1';
  2625.      else
  2626.        s[32-i] = '0';
  2627.      l = l >> 1;
  2628.   }
  2629.  
  2630.   /* --- Replace leading 0's with spaces --- */
  2631.   for ( i = 0; i < 32; i++)
  2632.   {
  2633.      if ( s[i] == '1' ) break;
  2634.      s[i] = ' ';
  2635.   }
  2636.  
  2637.   lstrip(s);
  2638.  
  2639.   return s;
  2640. }
  2641.  
  2642. void message( char *msg )
  2643. {
  2644.    io_gotoxy( 1, 2 );
  2645.  
  2646.    io_printf( "%-79.79s", msg );
  2647.    io_gotoxy( strlen( msg ), 2 );
  2648.    io_refresh();
  2649.  
  2650.    (void)io_inchar( );
  2651. }
  2652.  
  2653. void get_file_length( void )
  2654. {
  2655.     static old_file_length = -1;
  2656.  
  2657.      /* -- Always get end-of-file in case file length changes while editing -*/
  2658.      fseek( file, 0L, SEEK_END );
  2659.      filelen = ftell( file );   /* Get file length */ 
  2660.  
  2661.      /* --- Update display to screen of file length --- */
  2662.      if ( filelen != old_file_length )
  2663.      {
  2664.        io_gotoxy( 31, 1 );
  2665.        io_printf( "%-10ld", filelen );
  2666.        old_file_length = filelen;
  2667.      }
  2668. }
  2669.  
  2670.  
  2671. void rstrip( char *s )
  2672. {
  2673.    long i;
  2674.  
  2675.    for( i = strlen(s)-1; i >= 0; i--)
  2676.    {
  2677.      if ( s[i] == ' ' || s[i] == '\t' || s[i] == '\n')
  2678.        s[i] = 0;
  2679.      else
  2680.        break;
  2681.      
  2682.    }
  2683.  
  2684. }
  2685.  
  2686. void lstrip( char *s )
  2687. {
  2688.    long i;
  2689.    long len;
  2690.    long ptr=0;
  2691.  
  2692.    len = strlen(s);
  2693.    
  2694.    /* -- find first non-blank -- */
  2695.    for (i = 0; i < len; i++)
  2696.    {
  2697.      if ( s[i] != ' ' && s[i] != '\t' && s[i] != '\n')
  2698.      {
  2699.        ptr = i;
  2700.        break;
  2701.      }
  2702.    }
  2703.  
  2704.    if ( ptr == 0 ) return;  /* -- Nothing to strip -- */
  2705.  
  2706.    /* -- Copy elements over -- */
  2707.  
  2708.    for (i = 0; ptr < len; i++, ptr++)
  2709.    {
  2710.       s[i] = s[ptr];
  2711.  
  2712.    }
  2713.    s[i] = 0;
  2714. }
  2715.  
  2716. char valid_char( char a )
  2717. {
  2718.    short s;
  2719.    s = (short)a & 0x00FF;
  2720.    if ( s < (short)io_MIN_VALID_CHARACTER ||
  2721.         s > (short)io_MAX_VALID_CHARACTER )
  2722.    {
  2723.      return (char)'.';
  2724.    }
  2725.    else
  2726.    { 
  2727.      return a;
  2728.    }
  2729. }
  2730.  
  2731. int files_are_same( char *file1, char *file2)
  2732. {
  2733.   /*
  2734.   ** Return value: 1 = files are same
  2735.   **               0 = files are not same
  2736.   */
  2737.   char *ptr1;
  2738.   char *ptr2;
  2739.   long i = 0;
  2740.  
  2741.   ptr1 = strrchr( file1, '/' );
  2742.   if ( ptr1 == (char *)0 )
  2743.   {
  2744.      ptr1 = strrchr( file1, '\\' );
  2745.   }
  2746.   else
  2747.   {
  2748.      ptr1++;
  2749.   }
  2750.  
  2751.   if ( ptr1 == (char *)0 )
  2752.   {
  2753.     ptr1 = file1;
  2754.   }
  2755.   else
  2756.   {
  2757.      ptr1++;
  2758.   }
  2759.  
  2760.   ptr2 = strrchr( file2, '/' );
  2761.   if ( ptr2 == (char *)0 )
  2762.   {
  2763.      ptr2 = strrchr( file2, '\\' );
  2764.   }
  2765.   else
  2766.   {
  2767.     ptr2++;
  2768.   }
  2769.  
  2770.   if ( ptr2 == (char *)0 )
  2771.   {
  2772.     ptr2 = file2;
  2773.   }
  2774.   else
  2775.   {
  2776.     ptr2++;
  2777.   }
  2778.  
  2779.   if ( io_MIXED_CASE_FILENAMES )
  2780.   {
  2781.  
  2782.     do
  2783.     {
  2784.        if ( ptr1[i] != ptr2[i] ) return 0;
  2785.        i++;
  2786.     }
  2787.     while( ptr1[i-1] != (char)0 && ptr2[i-1] != (char)0 );
  2788.   }
  2789.   else
  2790.   {
  2791.     do
  2792.     {
  2793.        if ( toupper(ptr1[i]) != toupper(ptr2[i]) ) return 0;
  2794.        i++;
  2795.     }
  2796.     while ( ptr1[i-1] != (char)0 && ptr2[i-1] != (char)0 );
  2797.   }
  2798.   
  2799.   return 1;
  2800. }
  2801.  
  2802. short input_line( char *str, short col, short row, short len,
  2803.                   short startpos, int *exitlist, char *options )
  2804. {
  2805.    short i;
  2806.    short break_flag;
  2807.    short curpos;
  2808.    short keyhit = 0;
  2809.    int   null_flag;
  2810.    char *numeric      = (char *)0;
  2811.    char *hex          = (char *)0;
  2812.    char *binary       = (char *)0;
  2813.    char *instant_exit = (char *)0;
  2814.    char *zap          = (char *)0;
  2815.    char *exit_left    = (char *)0;
  2816.    char *exit_right   = (char *)0;
  2817.    char *pre_validate = (char *)0;
  2818.  
  2819.    numeric      = strstr(options, ".NUMERIC");
  2820.    hex          = strstr(options, ".HEX");
  2821.    binary       = strstr(options, ".BINARY");
  2822.    instant_exit = strstr(options, ".INSTANT_EXIT");
  2823.    zap          = strstr(options, ".ZAP");
  2824.    exit_left    = strstr(options, ".EXIT_LEFT");
  2825.    exit_right   = strstr(options, ".EXIT_RIGHT");
  2826.    pre_validate = strstr(options, ".PRE_VALIDATE");
  2827.  
  2828.  
  2829.    curpos = startpos;
  2830.    if ( pre_validate != (char *)0 )
  2831.    {
  2832.      for ( i = 0; i < len; i++ )
  2833.      {
  2834.        if ( str[i] == (char)0 ) break;
  2835.        str[i] = valid_char(str[i]);
  2836.      }
  2837.    }
  2838.  
  2839.    /*----------------------------------------------
  2840.        Process keystrokes
  2841.     *----------------------------------------------*/
  2842.  
  2843.    io_gotoxy(col, row);
  2844.    io_printf("%-*.*s", len, len, str);
  2845.  
  2846.    do                          /* Beginning of key-processing block */
  2847.    {
  2848.      io_gotoxy(col+curpos-1,row);
  2849.      io_refresh();
  2850.  
  2851.      keyhit = io_inchar();
  2852.  
  2853.      if ( exitlist != (int *)0 )
  2854.      {
  2855.        break_flag = 0;
  2856.        for ( i = 0; exitlist[i] != (int)0 && break_flag == 0; i++)
  2857.        {
  2858.          if (keyhit == exitlist[i]) break_flag = 1;
  2859.        }
  2860.        if ( break_flag ) break;
  2861.      }
  2862.  
  2863.      if ( keyhit == io_BACKSPACE || keyhit == io_CTRL_H )
  2864.      {
  2865.          zap = (char *)0;
  2866.          if (curpos > 1) curpos--;
  2867.          if (curpos <= len) str[curpos-1] = ' ';
  2868.          io_gotoxy(col+curpos-1,row);
  2869.          io_printf(" ");
  2870.  
  2871.      }
  2872.      else if ( keyhit == io_LEFT || keyhit == io_CTRL_L )
  2873.      {
  2874.          zap = (char *)0;
  2875.          if (curpos > 1)
  2876.            curpos--;
  2877.          else
  2878.          {
  2879.            if ( exit_left ) break;
  2880.          }
  2881.      }
  2882.      else if ( keyhit == io_RIGHT || keyhit == io_CTRL_R )
  2883.      {
  2884.          zap = (char *)0;
  2885.          if (curpos < len)
  2886.            curpos++;
  2887.          else
  2888.          {
  2889.            if ( exit_right ) break;
  2890.          }
  2891.      }
  2892.      else
  2893.      {
  2894.          if (keyhit >= 32 && keyhit <= io_MAX_VALID_CHARACTER )  
  2895.          {
  2896.            if ( numeric != (char *)0 &&
  2897.                strchr("0123456789", (char)keyhit) == (char *)0 ) continue;
  2898.  
  2899.            if ( hex != (char *)0 && strchr("0123456789ABCDEFabcdef",
  2900.                 (char)keyhit) == (char *)0 ) continue;
  2901.  
  2902.            if ( binary != (char *)0 &&
  2903.                strchr("01", (char)keyhit) == (char *)0 ) continue;
  2904.  
  2905.            if ( hex && strchr("abcdef", keyhit) ) keyhit = toupper(keyhit);
  2906.  
  2907.            if ( zap )
  2908.            {
  2909.               curpos = 1;
  2910.               sprintf( str, "%*s", len, " " );
  2911.               io_gotoxy(col,row);
  2912.               io_puts(str);
  2913.               io_gotoxy(col+curpos-1,row);
  2914.               zap = (char *)0;
  2915.            }
  2916.  
  2917.            /* --- Regular character entered -- */
  2918.            if ( curpos > len ) curpos = len;
  2919.            io_putc( keyhit );
  2920.  
  2921.            /* --- Pad with spaces if needed -- */
  2922.            for (i = 0, null_flag = FALSE; i < curpos; i++)
  2923.            {
  2924.              if (null_flag == TRUE)
  2925.              {
  2926.                str[i] = ' ';
  2927.                continue;
  2928.              }
  2929.              if ( str[i] == (char)0 ) null_flag = TRUE;
  2930.            }
  2931.            if ( null_flag == TRUE ) str[curpos] = (char)0;
  2932.  
  2933.            str[curpos-1]=(char)keyhit;
  2934.            if (curpos < len ) curpos++;
  2935.          }
  2936.          else
  2937.          {
  2938.            break;
  2939.          }
  2940.      }
  2941.    }while( !instant_exit );   /* End of do-while loop */
  2942.  
  2943.    return keyhit;
  2944. }
  2945.